Skip to content

Conversation

@ssdeanx
Copy link
Owner

@ssdeanx ssdeanx commented Jan 16, 2026

No description provided.

Widen RequestContext generics to unknown in business/legal agents,
comment out pgQueryTool, and tidy imports/formatting in A2A
coordinators.
Copilot AI review requested due to automatic review settings January 16, 2026 15:42
@vercel
Copy link

vercel bot commented Jan 16, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Review Updated (UTC)
agent-stack Error Error Jan 16, 2026 3:45pm

Copy link

@sourcery-ai sourcery-ai bot left a comment

Choose a reason for hiding this comment

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

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

Copy link

@greptile-apps greptile-apps bot left a comment

Choose a reason for hiding this comment

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

Your free trial has ended. If you'd like to continue receiving code reviews, you can add a payment method here.

@github-actions
Copy link

🤖 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.

@coderabbitai
Copy link

coderabbitai bot commented Jan 16, 2026

Summary by CodeRabbit

  • New Features

    • Added comprehensive tool integrations for browser automation, calculations, sandboxing, command execution, GitHub operations, cryptocurrency/stock data, and more.
    • Enhanced landing page with improved scroll-based animations and visual effects.
  • Documentation

    • Added tool integration guide detailing component interfaces and usage patterns.
  • Chores

    • Updated dependencies across AI SDK packages, TanStack React Query, and related libraries.

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

Walkthrough

This pull request introduces multiple tool UI card components for rendering AI agent results, replaces Framer Motion with GSAP for the landing hero animation, updates dependencies, removes TypeScript error suppressions, expands the A2A coordinator agent configuration, and broadens TypeScript compiler options. Changes span animation library migration, new presentational components, type system tightening, and agent orchestration expansion.

Changes

Cohort / File(s) Summary
Animation Library Migration
app/components/landing-hero.tsx
Replaces Framer Motion with GSAP-based timeline and ScrollTrigger animations; introduces heroRef for scroll-driven parallax effects and staggered element animations via shared hero-element class.
Dependency Updates
package.json
Bumps version to 1.1.3; updates @ai-sdk/* packages, mastra-related packages, TanStack React Query, ai package; adds @xterm/xterm; removes ai-sdk-provider-claude-code.
Type System Cleanup
src/components/ai-elements/confirmation.tsx, tool.tsx
Removes @ts-expect-error comments suppressing type errors; exposes potential typing issues without changing runtime behavior.
Browser Tool UI Cards
src/components/ai-elements/tools/browser-tool.tsx
Introduces 7 exported card components (ScreenshotCard, PdfGeneratorCard, BrowserToolCard, ClickAndExtractCard, FillFormCard, GoogleSearchCard, MonitorPageCard) with loading/error states, copy/download actions, and state-driven rendering.
Calculator Tool UI Cards
src/components/ai-elements/tools/calculator-tool.tsx
Adds 3 exported components (CalculatorCard, UnitConverterCard, MatrixCalculatorCard) with variable display toggles, copy/download, and JSON rendering for results.
E2B Sandbox Tool UI Cards
src/components/ai-elements/tools/e2b-sandbox-tool.tsx
Replaces monolithic component with 12 specialized exported cards (CreateSandboxCard, WriteFileCard, WriteFilesCard, ListFilesCard, DeleteFileCard, CreateDirectoryCard, GetFileInfoCard, CheckFileExistsCard, GetFileSizeCard, WatchDirectoryCard, RunCommandCard, RunCodeCard) with modular per-tool rendering.
Execa & Polygon Tool UI Cards
src/components/ai-elements/tools/execa-tool.tsx, polygon-tools.tsx
Introduces ExecaToolCard for command execution results with filtering and line-number toggle; adds 6 polygon cards (PolygonStockQuotesCard, PolygonStockAggregatesCard, PolygonStockFundamentalsCard, PolygonCryptoQuotesCard, PolygonCryptoAggregatesCard, PolygonCryptoSnapshotsCard) with search filters and data export.
GitHub & Tool Refactoring
src/components/ai-elements/tools/github-tools.tsx, link-extractor-tool.tsx, site-map-extractor-tool.tsx, web-scraper-tool.tsx
Refactors GitHub tool components (RepositoryCard, PullRequestList signatures simplified); loosens type assertions in link-extractor, site-map-extractor, and web-scraper; formatting adjustments and ScrollArea integration.
Tool Types & Exports
src/components/ai-elements/tools/types.ts, index.ts, AGENTS.md
Adds CalculatorUITool, UnitConverterUITool, MatrixCalculatorUITool types; expands index.ts re-exports for all new card components; introduces AGENTS.md documentation describing tool UI components, system flow, and integration patterns.
Agent Coordinator Configuration
src/mastra/a2a/a2aCoordinatorAgent.ts, codingA2ACoordinator.ts, src/mastra/agents/businessLegalAgents.ts
Expands A2A coordinator agents map, workflows map, and instructions; adds maxRetries, tools, scorers config; applies GoogleGenerativeAIProviderOptions satisfies constraints; broadens requestContext typing in business legal agents; comments out pgQueryTool from multiple agents.
Tool & Utility Type Adjustments
src/mastra/tools/github.ts, src/utils/streamUtils.ts
Tightens commit/PR mapping types with GitHubCommit interface; relaxes handleTextStream generic constraint from unknown to any for the second StreamTextResult parameter.
TypeScript Configuration Expansion
tsconfig.json
Expands compiler options with allowJs, incremental, isolatedModules, jsx, baseUrl, paths, and Next.js plugin; broadens include/exclude arrays with extensive file globs and directory patterns; adds path mappings.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~50 minutes

Possibly related PRs

  • feat: enhance coding agents and workflows #10 — Modifies src/mastra/a2a/codingA2ACoordinator.ts with model, providerOptions, and workflows changes overlapping the main PR's coordinator configuration updates.
  • Develop #101 — Refactors src/components/ai-elements/tools/e2b-sandbox-tool.tsx into per-tool Card components, directly aligning with the main PR's substantial e2b-sandbox-tool restructuring.
  • feat: enhance AI tools and agents with new functionalities #70 — Modifies tools/types/exports and multi-agent coordinator code, including src/components/ai-elements/tools/types.ts, tool index re-exports, and A2A coordinator files, showing overlap with the main PR's tool and coordinator expansions.

Poem

🐰 The tools sing out in cards so bright,
GSAP brings the scroll to light,
Seven browsers, calc and sand,
Agent networks, hand in hand.
Types unshackled, config sprawls,
Rabbit hops through data halls! 🏃‍♂️✨

🚥 Pre-merge checks | ❌ 3
❌ Failed checks (1 warning, 2 inconclusive)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 30.51% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Title check ❓ Inconclusive The title 'Develop' is vague and does not convey meaningful information about the changeset, which includes major updates across UI components, animations, dependencies, and agents. Replace with a descriptive title that captures the main changes, such as 'Add tool UI cards and update animation system' or 'Refactor tool components and upgrade dependencies'.
Description check ❓ Inconclusive No pull request description was provided by the author, making it impossible to assess whether the description relates to the changeset. Add a detailed description explaining the scope of changes, including new tool UI components, animation system updates, dependency upgrades, and agent modifications.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch develop

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

❤️ Share

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

@github-actions
Copy link

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

@gemini-code-assist
Copy link
Contributor

Summary of Changes

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

This pull request delivers a substantial upgrade to the user interface for interacting with AI agent tools, providing a more intuitive and feature-rich experience. The changes encompass a broad range of functionalities, from web interactions and data processing to code execution and financial analysis, all presented through dedicated and interactive UI components. Alongside these UI enhancements, the PR includes crucial dependency updates and type-related refinements, ensuring the system remains robust and aligned with the latest development practices.

Highlights

  • New UI Components for AI Tools: Introduced a comprehensive suite of new and refactored UI components for various AI agent tools, including browser automation (screenshots, PDF generation, web scraping, form filling, Google search), mathematical calculations (calculator, unit converter, matrix operations), E2B sandbox interactions (file operations, command execution, code execution), GitHub repository data (commits, PRs, issues), and Polygon financial data (stock and crypto quotes, aggregates, fundamentals).
  • Animation Library Migration: Migrated the animation library in app/components/landing-hero.tsx from framer-motion to gsap and ScrollTrigger, implementing staggered entrance animations and parallax effects for a more dynamic user experience.
  • Dependency Updates and Type Safety Improvements: Updated numerous @ai-sdk and @mastra dependencies to their latest beta versions in package.json. Enhanced type safety across several agent configurations and tool definitions by removing @ts-expect-error comments, introducing new interfaces (e.g., GitHubCommit), and refining type castings.
  • Enhanced E2B Sandbox Tooling: The E2B Sandbox tool component has been significantly refactored into granular, specialized UI components, each tailored to a specific sandbox action (e.g., CreateSandboxCard, RunCommandCard, ListFilesCard), providing richer interaction and clearer output for each operation.
  • New Documentation for Agent UI Components: Added a new AGENTS.md documentation file that details the purpose, persona, structure, system flow, and integration patterns for the AI agent UI components, improving clarity and maintainability for developers.
Using Gemini Code Assist

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

Invoking Gemini

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

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

Customization

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

Limitations & Feedback

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

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

Footnotes

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

Copy link
Contributor

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

Choose a reason for hiding this comment

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

Code Review

This pull request introduces a significant number of new UI components for rendering agent tool outputs and refactors the landing page animation to use GSAP. While these are valuable additions, there are several recurring issues across the new components, primarily related to TypeScript type safety, where as any is used frequently to bypass type errors. This indicates underlying issues with type definitions that should be addressed to improve code maintainability and prevent runtime errors. Additionally, I've identified a critical misconfiguration in tsconfig.json, a potential memory leak in the new GSAP animation, and other areas for improvement detailed in the comments.

Comment on lines +45 to +93
"/.next/types/**/*.ts",
"/.next/dev/types/**/*.ts",
"app/**/*.ts",
"/app/**/*.ts",
"app/**/*.tsx",
"/app/**/*.tsx",
"src/mastra/workflows/*.ts",
"/app/**/*.mdx ",
"src/**/*.ts",
"/src/**/*.js",
"/src/**/*.tsx",
"src/**/*.ts",
"src/**/*.tsx",
"src/mastra/types/**/*.d.ts",
"types/**/*.d.ts",
"utils/**/*.ts",
"/lib/**/*.ts",
"utils/**/*.tsx",
"styles/**/*.ts",
"styles/**/*.tsx",
"ui/**/*.ts",
"/ui/**/*.ts",
"/ui/**/*.tsx",
"ui/**/*.tsx",
"lib/**/*.ts",
"/lib/**/*.ts",
"/lib/**/*.tsx",
"lib/**/*.tsx",
"hooks/**/*.ts",
"/hooks/**/*.ts",
"/hooks/**/*.tsx",
"hooks/**/*.tsx",
"pages/**/*.ts",
"pages/**/*.tsx",
"convex/**/*.ts",
"/convex/**/*.ts",
"/convex/**/*.tsx",
"convex/**/*.tsx",
"convex/**/*.d.ts",
"convex/mastra/**/*.ts",
"convex/**/*.js",
// Tests are excluded from the main typecheck run to avoid typechecking test-only imports
// that may pull in declaration files with unsupported syntax from node_modules.
"types/**/*.d.ts",
"/tests/**/*.ts",
"/types/**.d.ts",
"/public/",
".next/types/**/*.ts",
".next/dev/types/**/*.ts"
Copy link
Contributor

Choose a reason for hiding this comment

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

critical

Many of the paths in the include array start with a leading /, such as "/app/**/*.ts". In a tsconfig.json file, paths are typically relative to the baseUrl (which is ./ in this case). A leading slash refers to the root of the filesystem, which is almost certainly not what is intended here.

This misconfiguration can cause files to be missed by the TypeScript compiler, leading to an incomplete type-checking process and potentially hiding errors. Please remove the leading slashes from these paths.

    "instrumentation.ts",
    ".next/types/**/*.ts",
    ".next/dev/types/**/*.ts",
    "app/**/*.ts",
    "app/**/*.tsx",
    "src/mastra/workflows/*.ts",
    "app/**/*.mdx",
    "src/**/*.ts",
    "src/**/*.js",
    "src/**/*.tsx",
    "src/mastra/types/**/*.d.ts",
    "types/**/*.d.ts",
    "utils/**/*.ts",
    "lib/**/*.ts",
    "utils/**/*.tsx",
    "styles/**/*.ts",
    "styles/**/*.tsx",
    "ui/**/*.ts",
    "ui/**/*.tsx",
    "lib/**/*.ts",
    "lib/**/*.tsx",
    "hooks/**/*.ts",
    "hooks/**/*.tsx",
    "pages/**/*.ts",
    "pages/**/*.tsx",
    "convex/**/*.ts",
    "convex/**/*.tsx",
    "convex/**/*.d.ts",
    "convex/mastra/**/*.ts",
    "convex/**/*.js",
    // Tests are excluded from the main typecheck run to avoid typechecking test-only imports
    // that may pull in declaration files with unsupported syntax from node_modules.
    "types/**/*.d.ts",
    "tests/**/*.ts",
    "public/"

Comment on lines +14 to +44
useGSAP(() => {
const tl = gsap.timeline()

// Stagger entrance animation for child elements
tl.fromTo(
'.hero-element',
{ opacity: 0, y: 20 },
{
opacity: 1,
y: 0,
duration: 0.6,
ease: 'power2.out',
stagger: 0.1,
}
)

// Add ScrollTrigger for parallax effect
ScrollTrigger.create({
trigger: heroRef.current,
start: 'top bottom',
end: 'bottom top',
scrub: 1,
onUpdate: (self) => {
const progress = self.progress
gsap.set(heroRef.current, {
y: -progress * 50, // Parallax effect
scale: 1 + progress * 0.05, // Slight zoom
})
},
})
})
Copy link
Contributor

Choose a reason for hiding this comment

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

high

The useGSAP hook should be scoped to the heroRef to ensure proper cleanup of animations and especially the ScrollTrigger instance. ScrollTrigger.create() can cause memory leaks if not properly cleaned up when the component unmounts. By providing a scope, @gsap/react can automatically handle this for you.

    useGSAP(() => {
        const tl = gsap.timeline()

        // Stagger entrance animation for child elements
        tl.fromTo(
            '.hero-element',
            { opacity: 0, y: 20 },
            {
                opacity: 1,
                y: 0,
                duration: 0.6,
                ease: 'power2.out',
                stagger: 0.1,
            }
        )

        // Add ScrollTrigger for parallax effect
        ScrollTrigger.create({
            trigger: heroRef.current,
            start: 'top bottom',
            end: 'bottom top',
            scrub: 1,
            onUpdate: (self) => {
                const progress = self.progress
                gsap.set(heroRef.current, {
                    y: -progress * 50, // Parallax effect
                    scale: 1 + progress * 0.05, // Slight zoom
                })
            },
        })
    }, { scope: heroRef })


if (errorText) return <ErrorCard title="Screenshot Failed" message={errorText} />
if (!output) {
return <LoadingCard title={`Taking screenshot of ${(input as any).url}...`} icon={<Loader2 className="size-4 animate-spin" />} />
Copy link
Contributor

Choose a reason for hiding this comment

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

high

The use of (input as any).url and similar as any type assertions is prevalent throughout this file and other new tool components. This bypasses TypeScript's type safety and is a code smell, indicating that the prop types (e.g., ScreenshotUITool['input']) may not be correctly defined or inferred.

Instead of casting to any, please ensure the types are correctly defined so you can access properties directly (e.g., input.url). This will make the code more robust, maintainable, and less prone to runtime errors.

Suggested change
return <LoadingCard title={`Taking screenshot of ${(input as any).url}...`} icon={<Loader2 className="size-4 animate-spin" />} />
return <LoadingCard title={`Taking screenshot of ${input.url}...`} icon={<Loader2 className="size-4 animate-spin" />} />

Comment on lines +317 to +324
<Button size="icon" variant="ghost" onClick={() => {
const bytes = new TextEncoder().encode(content)
const binaryString = Array.from(bytes, byte => String.fromCharCode(byte)).join('')
const base64 = btoa(binaryString)
downloadFileFromBase64('extracted.html', base64, 'text/html')
}}>
<Download className="size-4" />
</Button>
Copy link
Contributor

Choose a reason for hiding this comment

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

high

The logic to download the extracted content is inefficient and potentially incorrect for non-ASCII characters. The conversion from a string to a base64 representation of its UTF-8 bytes is complex and error-prone as implemented.

A much cleaner and more reliable approach is to create a Blob directly from the content string and then generate an object URL for the download link. This avoids manual encoding and handles character sets correctly.

            <Button size="icon" variant="ghost" onClick={() => {
              const blob = new Blob([content], { type: 'text/html' });
              const url = URL.createObjectURL(blob);
              const a = document.createElement('a');
              a.href = url;
              a.download = 'extracted.html';
              document.body.appendChild(a);
              a.click();
              a.remove();
              URL.revokeObjectURL(url);
            }}>

input,
output,
errorText,
}: ToolProps<any, any>) {
Copy link
Contributor

Choose a reason for hiding this comment

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

high

The CommitHistoryList component is using ToolProps<any, any>, which defeats the purpose of using TypeScript. This leads to a loss of type safety for the input and output props, forcing the use of any casts within the component.

You should use the specific tool types inferred from your Zod schemas, like ToolProps<ListCommitsUITool['input'], ListCommitsUITool['output']>, to ensure type safety and improve code quality.

Suggested change
}: ToolProps<any, any>) {
}: ToolProps<ListCommitsUITool['input'], ListCommitsUITool['output']>) {

requestContext,
}: {
requestContext: RequestContext<BusinessRuntimeContext>
requestContext: RequestContext<unknown>
Copy link
Contributor

Choose a reason for hiding this comment

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

high

The requestContext type has been changed from RequestContext<BusinessRuntimeContext> to RequestContext<unknown>. This is a significant regression in type safety. It forces the use of as any casts later in the code to access properties, which can lead to runtime errors and makes the code harder to maintain.

Please revert this to use the specific BusinessRuntimeContext to ensure type safety.

Suggested change
requestContext: RequestContext<unknown>
requestContext: RequestContext<BusinessRuntimeContext>

Comment on lines +64 to +66
} catch {
// ignore
}
Copy link
Contributor

Choose a reason for hiding this comment

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

medium

This catch block is empty, which swallows errors silently. If an error occurs during the file download process, it will fail without any indication, making debugging difficult. At a minimum, you should log the error to the console. This issue is present in multiple helper functions across the new tool components.

Suggested change
} catch {
// ignore
}
} catch (error) {
console.error('Failed to download file from base64:', error);
}

Comment on lines +106 to +115
function mapToBundledLanguage(lang?: string): any {
if (!lang) return 'bash'
const l = lang.toLowerCase()
if (l.includes('ts')) return 'typescript'
if (l.includes('js') || l.includes('javascript')) return 'javascript'
if (l.includes('py') || l.includes('python')) return 'python'
if (l.includes('json')) return 'json'
if (l.includes('html')) return 'html'
return 'bash'
}
Copy link
Contributor

Choose a reason for hiding this comment

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

medium

The mapToBundledLanguage function has a return type of any. This undermines type safety. You should define a specific type for the supported languages from shiki and use it as the return type to leverage TypeScript's static analysis.

Suggested change
function mapToBundledLanguage(lang?: string): any {
if (!lang) return 'bash'
const l = lang.toLowerCase()
if (l.includes('ts')) return 'typescript'
if (l.includes('js') || l.includes('javascript')) return 'javascript'
if (l.includes('py') || l.includes('python')) return 'python'
if (l.includes('json')) return 'json'
if (l.includes('html')) return 'html'
return 'bash'
}
type BundledLanguage = 'typescript' | 'javascript' | 'python' | 'json' | 'html' | 'bash';
function mapToBundledLanguage(lang?: string): BundledLanguage {
if (!lang) return 'bash'
const l = lang.toLowerCase()
if (l.includes('ts')) return 'typescript'
if (l.includes('js') || l.includes('javascript')) return 'javascript'
if (l.includes('py') || l.includes('python')) return 'python'
if (l.includes('json')) return 'json'
if (l.includes('html')) return 'html'
return 'bash'
}

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This pull request contains dependency updates and code refactoring improvements focused on type safety and formatting consistency across multiple components.

Changes:

  • Updated Mastra and AI SDK dependencies to latest beta versions
  • Replaced unknown type with any for improved type compatibility
  • Removed @ts-expect-error comments indicating AI SDK v6 compatibility
  • Added new calculator, polygon, browser, e2b-sandbox, and execa tool UI components
  • Reformatted code with consistent indentation and import organization

Reviewed changes

Copilot reviewed 21 out of 23 changed files in this pull request and generated 19 comments.

Show a summary per file
File Description
package.json Updated @mastra/* and @ai-sdk/* dependencies to latest beta versions, removed ai-sdk-provider-claude-code
tsconfig.json Reformatted with better indentation, added duplicate/redundant include patterns
src/utils/streamUtils.ts Changed generic type parameter from unknown to any
src/mastra/tools/github.ts Added GitHubCommit interface, replaced any type assertions with typed approach
src/mastra/agents/businessLegalAgents.ts Changed RequestContext generic from BusinessRuntimeContext to unknown, removed structuredOutput flags
src/mastra/a2a/*.ts Added type safety with satisfies GoogleGenerativeAIProviderOptions
src/components/ai-elements/tools/*.tsx Added new comprehensive tool UI components with extensive UX features
app/components/landing-hero.tsx Replaced framer-motion with GSAP animations

- User: ${userTier}
- Language: ${language}
- Research: Depth ${(research as any).depth ?? 'extensive'}, Scope ${(research as any).scope ?? 'full'}
- Analysis: Depth ${(analysis as any).depth ?? 'extensive'}, Scope ${(analysis as any).scope ?? 'full'}
Copy link

Copilot AI Jan 16, 2026

Choose a reason for hiding this comment

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

Using as any type assertions repeatedly to access properties defeats the purpose of TypeScript's type safety. Consider defining a proper interface for the analysis object or using type guards instead.

Copilot uses AI. Check for mistakes.
<CardHeader className="pb-3">
<CardTitle className="flex items-center gap-2 text-sm">
<Globe className="size-4 animate-pulse" />
Scraping {(input as any).url}...
Copy link

Copilot AI Jan 16, 2026

Choose a reason for hiding this comment

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

Multiple as any type assertions throughout this component bypass TypeScript's type checking. The input and output props should use the proper WebScraperUITool types imported at the top of the file instead of casting to any.

Copilot uses AI. Check for mistakes.
<CollapsibleContent
className={cn(
'data-[state=closed]:fade-out-0 data-[state=closed]:slide-out-to-top-2 data-[state=open]:slide-in-from-top-2 text-popover-foreground outline-none data-[state=closed]:animate-out data-[state=open]:animate-in',
'closed:fade-out-0 closed:slide-out-to-top-2 data-[state=open]:slide-in-from-top-2 text-popover-foreground outline-none closed:animate-out data-[state=open]:animate-in',
Copy link

Copilot AI Jan 16, 2026

Choose a reason for hiding this comment

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

The data attribute selectors have been changed from data-[state=closed] to just closed, but this appears inconsistent with the data-[state=open] selectors that remain. This could be a bug if the component still uses data-state attributes. Verify that the CSS selectors match the actual DOM attributes being used.

Suggested change
'closed:fade-out-0 closed:slide-out-to-top-2 data-[state=open]:slide-in-from-top-2 text-popover-foreground outline-none closed:animate-out data-[state=open]:animate-in',
'data-[state=closed]:fade-out-0 data-[state=closed]:slide-out-to-top-2 data-[state=open]:slide-in-from-top-2 text-popover-foreground outline-none data-[state=closed]:animate-out data-[state=open]:animate-in',

Copilot uses AI. Check for mistakes.
Comment on lines 117 to 118
"ai-sdk-provider-gemini-cli": "^2.0.1",
"ai-sdk-provider-opencode-sdk": "^1.0.0",
Copy link

Copilot AI Jan 16, 2026

Choose a reason for hiding this comment

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

The package ai-sdk-provider-claude-code was removed from dependencies but ai-sdk-provider-gemini-cli and ai-sdk-provider-opencode-sdk remain. Ensure these packages are actually being used in the codebase, or consider documenting why certain provider packages are included while others are removed.

Suggested change
"ai-sdk-provider-gemini-cli": "^2.0.1",
"ai-sdk-provider-opencode-sdk": "^1.0.0",

Copilot uses AI. Check for mistakes.
export async function handleTextStream(
streamResult:
| StreamTextResult<ToolSet, unknown>
| StreamTextResult<ToolSet, any>
Copy link

Copilot AI Jan 16, 2026

Choose a reason for hiding this comment

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

Unexpected any. Specify a different type.

Suggested change
| StreamTextResult<ToolSet, any>
| StreamTextResult<ToolSet, unknown>

Copilot uses AI. Check for mistakes.
if (!output) {
return <LoadingCard title={`Computing matrix ${operationInput ?? 'operation'}`} icon={<Loader2 className="size-4 animate-spin" />} />
}
if (output && typeof output === 'object' && 'error' in output) {
Copy link

Copilot AI Jan 16, 2026

Choose a reason for hiding this comment

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

This use of variable 'output' always evaluates to true.

Suggested change
if (output && typeof output === 'object' && 'error' in output) {
if (typeof output === 'object' && 'error' in output) {

Copilot uses AI. Check for mistakes.
export function BrowserToolCard({ input, output, errorText }: BrowserToolCardProps) {
if (errorText) return <ErrorCard title="Browser Tool Failed" message={errorText} />
if (!output) return <LoadingCard title={`Browsing ${(input as any).url}...`} icon={<Loader2 className="size-4 animate-spin" />} />
if (output && typeof output === 'object' && 'error' in output) {
Copy link

Copilot AI Jan 16, 2026

Choose a reason for hiding this comment

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

This use of variable 'output' always evaluates to true.

Suggested change
if (output && typeof output === 'object' && 'error' in output) {
if (typeof output === 'object' && 'error' in output) {

Copilot uses AI. Check for mistakes.
</CardTitle>
<div className="flex items-center gap-2">
<Badge variant="secondary" className="text-xs">{formatBytes(contentLength)}</Badge>
{output && (output as any).message && <Badge variant="outline" className="text-xs">message</Badge>}
Copy link

Copilot AI Jan 16, 2026

Choose a reason for hiding this comment

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

This use of variable 'output' always evaluates to true.

Suggested change
{output && (output as any).message && <Badge variant="outline" className="text-xs">message</Badge>}
{(output as any).message && <Badge variant="outline" className="text-xs">message</Badge>}

Copilot uses AI. Check for mistakes.
export function ClickAndExtractCard({ input, output, errorText }: ClickAndExtractCardProps) {
if (errorText) return <ErrorCard title="Click & Extract Failed" message={errorText} />
if (!output) return <LoadingCard title={`Clicking ${(input as any).clickSelector} on ${(input as any).url}...`} icon={<Loader2 className="size-4 animate-spin" />} />
if (output && typeof output === 'object' && 'error' in output) return <ErrorCard title="Click & Extract Failed" message={(output as any).error ?? 'Unknown error'} />
Copy link

Copilot AI Jan 16, 2026

Choose a reason for hiding this comment

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

This use of variable 'output' always evaluates to true.

Suggested change
if (output && typeof output === 'object' && 'error' in output) return <ErrorCard title="Click & Extract Failed" message={(output as any).error ?? 'Unknown error'} />
if (typeof output === 'object' && 'error' in output) return <ErrorCard title="Click & Extract Failed" message={(output as any).error ?? 'Unknown error'} />

Copilot uses AI. Check for mistakes.
Comment on lines +387 to +388
if (!output) return <LoadingCard title={`Searching for ${(input as any).query}...`} icon={<Loader2 className="size-4 animate-spin" />} />
if (output && typeof output === 'object' && 'error' in output) return <ErrorCard title="Search Failed" message={(output as any).error ?? 'Unknown error'} />
Copy link

Copilot AI Jan 16, 2026

Choose a reason for hiding this comment

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

This use of variable 'output' always evaluates to true.

Suggested change
if (!output) return <LoadingCard title={`Searching for ${(input as any).query}...`} icon={<Loader2 className="size-4 animate-spin" />} />
if (output && typeof output === 'object' && 'error' in output) return <ErrorCard title="Search Failed" message={(output as any).error ?? 'Unknown error'} />
if (!output) return <LoadingCard title={`Searching for {(input as any).query}...`} icon={<Loader2 className="size-4 animate-spin" />} />
if (typeof output === 'object' && 'error' in output) return <ErrorCard title="Search Failed" message={(output as any).error ?? 'Unknown error'} />

Copilot uses AI. Check for mistakes.
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 40

Caution

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

⚠️ Outside diff range comments (2)
src/mastra/a2a/a2aCoordinatorAgent.ts (1)

19-48: Avoid sending raw userId in the system prompt (PII exposure).

Embedding a user identifier in LLM prompts risks leaking PII into model logs and outputs. Prefer masking or removing it from the prompt. As per coding guidelines, never include PII in code or logs.

🔒 Suggested masking approach
-import { pgMemory } from '../config/pg-storage'
+import { maskSensitiveMessageData, pgMemory } from '../config/pg-storage'
@@
   instructions: ({ requestContext }) => {
     const userId = requestContext.get('userId')
+    const maskedUserId = maskSensitiveMessageData(String(userId ?? ''))
     return {
@@
-userId: ${userId}
+userId: ${maskedUserId}
src/mastra/agents/businessLegalAgents.ts (1)

150-157: Avoid commented-out tool wiring.
Commented-out code violates the “remove, don’t comment” guideline. Remove the line or gate tool exposure via config/feature flags.

🧹 Cleanup
-    //  pgQueryTool,
🤖 Fix all issues with AI agents
In `@app/components/landing-hero.tsx`:
- Line 1: Add a TSDoc file header block above the existing 'use client'
directive in this file: include `@fileoverview` with a short description, `@author`
with the author name, `@copyright` with year/owner, and `@license` with the
project's license identifier; ensure the header is a proper multi-line TSDoc
comment placed immediately before the 'use client' line so tooling picks it up.
- Around line 12-44: Scope the GSAP animation to this component, guard against a
null ref, run the effect only once, and clean up ScrollTrigger on unmount: wrap
the timeline and selector usage in a gsap.context tied to heroRef (use
context.selector or context() so '.hero-element' targets only descendants), add
a null check for heroRef.current before creating ScrollTrigger, pass an empty
dependency array to useGSAP to ensure a single run, and return a cleanup that
kills the timeline/context and calls ScrollTrigger.getAll()/kill() or kills the
specific ScrollTrigger instance created (reference the ScrollTrigger returned
from ScrollTrigger.create) to remove listeners when the component unmounts.

In `@src/components/ai-elements/tools/AGENTS.md`:
- Around line 1-4: Replace the HTML meta comment with proper YAML front matter
containing the fields title, version, last_updated, applies_to, tags, and status
(you may retain the existing AGENTS-META HTML comment above or below it if
desired), and change the top-level H1 heading (“# Tools Directory…”) to an H2
(“## Tools Directory…”) so the file conforms to docs guidelines; ensure the YAML
keys match the values in the AGENTS-META block (title, version, last_updated,
applies_to, tags, status) and remove the leading H1 syntax.

In `@src/components/ai-elements/tools/browser-tool.tsx`:
- Around line 103-109: The ScreenshotCardProps interface defines a toolCallId
property that isn't used by the component (and the same unused prop appears
across other card interfaces); either remove toolCallId from ScreenshotCardProps
(and the other card props like ImageCardProps, TextCardProps, etc.) or update
the corresponding card components to actually use toolCallId (e.g., include it
as a React key/debug id attribute or render it for debugging). Locate the unused
symbol ScreenshotCardProps and any similarly named interfaces in this file and
either delete the toolCallId field from their definitions and all places passing
it, or wire toolCallId into the component render (e.g., data-tool-call-id or key
usage) consistently across the card components.
- Line 30: The import statement includes unused symbols useEffect and useRef;
remove them from the import so only used symbols (useState and type ChangeEvent
if used) remain. Update the import line that currently mentions useEffect and
useRef to only import the actually used hooks/types (e.g., ensure useState and
ChangeEvent are kept if referenced elsewhere in this module such as in the
BrowserTool component), and run a quick build or linter to confirm no missing
imports remain.
- Around line 419-421: Replace the copy-paste redundant fallbacks in the JSX
render: change the title expression (currently r.title ?? r.title) to a sensible
chain like r.title ?? r.name ?? r.url, and change the snippet expression
(currently r.snippet ?? r.description ?? r.snippet) to a proper fallback chain
such as r.snippet ?? r.description ?? r.summary ?? '' so the component (in
src/components/ai-elements/tools/browser-tool.tsx where r.title and r.snippet
are used) shows meaningful alternate fields instead of repeating the same
property.
- Around line 130-132: The current empty catch in browser-tool.tsx swallows
clipboard errors; update the try/catch around the clipboard write (the copy
handler—e.g., the function handling copyToClipboard/onCopy) to catch the error
as a variable (catch (err)) and surface feedback: log the error (console.error
or a shared logger) and show user feedback (e.g., call the existing
toast/notification helper or set a component state like clipboardError) so
permissions or other failures are visible to the user. Ensure the catch includes
the error variable and invokes the app's notification method rather than
silently ignoring failures.
- Around line 64-67: The empty catch in
src/components/ai-elements/tools/browser-tool.tsx silently swallows errors;
change the catch to capture the exception (catch (err)) and log it and/or
surface it to the user (e.g., use existing logger or console.error and update
local state or call an error handler) inside the BrowserTool handler where the
catch sits so failures are visible for debugging and the UI can show an error
message or fallback behavior.

In `@src/components/ai-elements/tools/calculator-tool.tsx`:
- Around line 83-88: The prop toolCallId declared on CalculatorCardProps,
UnitConverterCardProps, and MatrixCalculatorCardProps is unused; either remove
toolCallId from these interfaces and any JSX props passed down, or wire it into
the components for tracking/accessibility (e.g., add it as a data attribute like
data-tool-call-id or use it in an aria-describedby/element id or telemetry call
within CalculatorCard, UnitConverterCard, and MatrixCalculatorCard). Update the
interface definitions (CalculatorCardProps, UnitConverterCardProps,
MatrixCalculatorCardProps), the component parameter lists, and any call sites to
keep types consistent after removing or to add the data attribute/telemetry
usage if you choose to keep it.
- Line 12: Remove the unused import statement for Input from '@/ui/input' in the
calculator-tool.tsx file; locate the import near the top of the CalculatorTool
component (or the default export in that file) and delete the "Input" import so
only used imports remain, keeping the module free of unused symbols.
- Around line 305-313: The rendering assumes result is a 2D array but lacks
runtime validation; add a type guard before using (result as any[]).map that
verifies Array.isArray(result) and every element is also an array (e.g.,
isMatrix = Array.isArray(result) && result.every(r => Array.isArray(r))); if the
guard fails, render a safe fallback (error message or empty state) instead of
mapping to avoid runtime errors; update the mapping code that uses rIdx, row,
val, and cIdx to only run when isMatrix is true.
- Around line 94-107: The component uses many (input as any) and (output as any)
casts (see exprInput, result, formatted, expr, variables) instead of real types;
fix by importing the input/output types from the calculator tool's Zod schema
(or the InferUITool type for calculatorTool) and annotate the component props
and local variables accordingly so TypeScript narrows types without casts (or
add narrow type-guard functions for runtime checks like
isCalculatorInput/isCalculatorOutput), then remove the redundant as any casts
and rely on those typed properties when computing exprInput, result, formatted,
expr and variables.

In `@src/components/ai-elements/tools/e2b-sandbox-tool.tsx`:
- Around line 105-115: The function mapToBundledLanguage uses an unsafe any
return type; replace it with a precise union type (e.g.,
'bash'|'typescript'|'javascript'|'python'|'json'|'html') or import and use
shiki's BundledLanguage type and update the signature to return that type;
update the parameter typing (lang?: string) if needed and ensure all return
branches match the chosen type so TypeScript enforces correctness in
mapToBundledLanguage.
- Around line 288-307: In ListFilesCard, move all React hooks (e.g., the
useState call for fileQuery and any future hooks) to the top of the
ListFilesCard function before the early returns so hook order is stable; keep
derived values (files, fileCount, dirCount, filteredFiles) computed after the
early-return checks by using safe defaults (e.g., const files = (output as
any)?.files ?? []) or guard rendering with the existing errorText/output checks,
and ensure filteredFiles uses the fileQuery state but is only used when output
is present.
- Around line 355-357: Wrap the unprotected navigator.clipboard.writeText calls
in the Button onClick handlers so they handle rejections like the existing
examples (lines with proper handling near the earlier and later cases).
Specifically, update the onClick for the Copy button that currently does
onClick={() => navigator.clipboard.writeText(f.path)} and the other similar call
(around the later Copy action) to either make the handler async and surround
await navigator.clipboard.writeText(...) with try/catch or append a .catch(...)
to handle errors; reference the Button onClick handlers that use
navigator.clipboard.writeText in
src/components/ai-elements/tools/e2b-sandbox-tool.tsx and mirror the try/catch
pattern used at the earlier example in this file to log or surface the error
appropriately.
- Around line 90-103: The null check in function formatBytes uses loose equality
(bytes == null); change it to a strict check using === by testing both undefined
and null explicitly (e.g., bytes === undefined || bytes === null) so the eqeqeq
rule is satisfied; update the conditional in formatBytes to use that strict
check and keep the rest of the function unchanged.
- Around line 662-688: The RunCommandCard component calls hooks after early
returns which violates the Rules of Hooks; move all React hooks (useState,
useRef, useEffect) to the top of the component body immediately after the
function signature so they always run, then derive stdout/stderr using optional
chaining from output (e.g., const stdout = (output as any)?.stdout ?? '' and
const stderr = (output as any)?.stderr ?? ''), compute stdoutFiltered and
stderrFiltered after those hooks, and keep the existing conditional returns
(LoadingCard/ErrorCard) but base them on output/error existence only so hooks
are not executed conditionally (ensure symbols referenced: RunCommandCard,
useState, useRef, useEffect, stdout, stderr, stdoutFiltered, stderrFiltered,
stdoutBottomRef, stderrBottomRef).

In `@src/components/ai-elements/tools/execa-tool.tsx`:
- Around line 28-77: Extract the duplicated helpers ErrorCard, LoadingCard, and
downloadFile into a new shared module (e.g., create shared-helpers.tsx) and
export them; then replace the local definitions in execa-tool.tsx and
calculator-tool.tsx with imports from that shared file. Ensure the exported
signatures match the originals (ErrorCard({ title, message }), LoadingCard({
title, subtitle, icon }), downloadFile(filename, content, mime?)) so existing
usages in functions/components remain unchanged and build will succeed. Update
any relative import paths accordingly and remove the now-redundant local helper
definitions from both components.
- Around line 134-135: The current naive success heuristic in the
isLikelySuccess calculation (in src/components/ai-elements/tools/execa-tool.tsx)
treats any message not containing the substring "error" as success, which yields
false positives; change the logic to first check for an explicit numeric exit
code or status on the output object (e.g., output.exitCode, output.code, or
output.status) and treat 0 as success and non-zero as failure, and only if no
exit code is available fall back to a safer message analysis: test for
whole-word occurrences of "error" or "failed" using a word-boundary regex
(/\b(error|failed|failure)\b/i) and avoid negation-based checks like
!message.includes('error'); also expose or display the raw exit code (if
present) alongside the heuristic result so callers/users can see the
authoritative signal.
- Around line 74-77: The empty catch blocks in the execa execution and clipboard
handlers must not silently swallow errors: update the catch in the execa
execution (e.g., the function that runs the external command, likely named
runExeca or similar) to log the error (console.error in development) and surface
user feedback (e.g., call a toast, set an error state, or return a rejected
promise) instead of doing nothing; likewise update the clipboard-related catch
blocks in the copy handlers (e.g., handleCopyToClipboard / onCopyCommand) to log
the caught error and show a user-visible message (or fallback behavior) so
failures are visible for debugging and UX. Ensure logs are conditional on
environment if needed and preserve original error for further handling or
rethrowing when appropriate.
- Around line 21-26: The ExecaToolCardProps defines toolCallId but it isn't
used; update the ExecaToolCard component to use toolCallId for identification by
adding a data attribute and accessible labeling: set the root element (the
component container in ExecaToolCard) to include data-tool-call-id={toolCallId}
and set aria-labelledby to a generated id like `${toolCallId}-title` and add
that same id to the visible title/heading element inside the component;
alternatively, if you prefer to remove it, delete toolCallId from the
ExecaToolCardProps interface and all prop usages so the prop is no longer
declared.
- Around line 80-88: The component repeatedly asserts output as { message?:
string } when accessing the message; create a properly typed local variable or
interface to avoid repeated assertions: define an interface (e.g.,
OutputWithMessage) or a typed const like const typedOutput = output as
OutputWithMessage and then use typedOutput.message for setDisplayText initial
state, in useEffect, and anywhere else; update the symbols displayText,
setDisplayText, useEffect, and any occurrences of (output as { message?: string
})?.message to reference the new typed variable or interface.

In `@src/components/ai-elements/tools/github-tools.tsx`:
- Around line 169-174: Move the ToolProps<TInput, TOutput> interface so it's
declared immediately after the file imports and before any components that use
it (e.g., before CommitHistoryList) to ensure it's defined before first usage;
also reconcile the required toolCallId property by either making toolCallId
optional in the interface or updating the consuming components (such as
CommitHistoryList and any other components that don't use it) to supply a value,
keeping the interface consistent with actual usage.
- Around line 83-87: The CommitHistoryList component currently destructures an
unused input and uses ToolProps<any, any>, which sacrifices type safety; remove
the unused input from the parameter list and replace the any generics with
concrete interfaces (e.g., define CommitHistoryInput and CommitHistoryOutput
types that reflect the expected props shape) and update the function signature
to use ToolProps<CommitHistoryInput, CommitHistoryOutput> so the component and
its callers get proper typing (reference the CommitHistoryList function and
ToolProps generics when making the change).
- Around line 18-24: Remove the unused React type imports
(JSXElementConstructor, Key, ReactElement, ReactNode, ReactPortal) from the
top-level import in github-tools.tsx; locate the import statement that currently
imports these types and delete those identifiers so only used imports remain,
ensuring no other references to these types exist in functions or components
within the file (e.g., any usage in component signatures like GitHubTools or
exported helpers).
- Around line 429-431: When `issue` is falsy, don't return null; render a
user-facing placeholder instead so users get feedback. Replace the `if (!issue)
{ return null }` branch with a UI message (e.g., an EmptyState/placeholder or a
simple text element) that displays "No issue found" (or a translatable
equivalent) and optionally a hint or action (e.g., "Create an issue" or
"Refresh"); update the component that checks `issue` so it returns that message
element instead of null and ensure styling matches surrounding components.

In `@src/components/ai-elements/tools/link-extractor-tool.tsx`:
- Around line 96-103: Replace the inline ternary in the className on the element
rendered in links.map with the project's className utility (e.g., cn or clsx):
import the utility at the top of the file, then build the class list for the
mapped div using a base string "flex items-center gap-3 p-3 rounded-lg border"
plus a conditional object or conditional arguments that choose 'border-green-200
bg-green-50/50' when link.isValid and 'border-red-200 bg-red-50/50' otherwise;
update the component rendering in the LinkExtractorTool (the links.map callback)
to use that utility for clearer, more maintainable conditional classes.
- Line 67: The template uses (output as any).url but your earlier type assertion
at line 58 already included url but wasn't destructured; fix by destructuring
url from output where output is defined (e.g., const { url, ... } = output as
any) and replace "Links Extracted from {(output as any).url}" with "Links
Extracted from {url}", or alternatively remove the destructuring and
consistently use (output as any).url wherever url is needed; update the
component (LinkExtractorTool or the function that defines output) accordingly.
- Line 58: The destructuring uses broad any types — change the assertion to use
the tool's proper output type (e.g. use LinkExtractorUITool['output'] or an
explicit interface) instead of "{ links: any[], summary: any, url: string }";
update the declaration around the "output" variable in link-extractor-tool.tsx
and replace the inline any assertion at "const { links, summary } = output as {
... }" so that links and summary receive their concrete types (or add/adjust the
LinkExtractorUITool['output'] type definition if missing) to restore TypeScript
safety.

In `@src/components/ai-elements/tools/polygon-tools.tsx`:
- Around line 91-101: The prop toolCallId is declared but unused in
PolygonStockQuotesCard (and the other Polygon card components); either remove
toolCallId from the prop signatures or actually use it (for example as a React
key, a data-tool-call-id attribute, or include it in debug/error logging) to
avoid dead props—update the function signature for PolygonStockQuotesCard (and
the other Polygon*Card components) accordingly and clean up any related type
declarations so linting/TS errors are resolved.
- Around line 64-88: Extract the duplicated UI components and utility helpers
into a shared module (e.g., shared-ui.tsx or primitives.tsx): move LoadingCard
and ErrorCard (preserving their prop types and usage of
Card/CardHeader/CardTitle/CardContent and AlertCircle) plus utility functions
formatBytes, formatNumber, formatTime, downloadJSON and downloadFileFromBase64
into that module, export them, then update polygon-tools.tsx and
browser-tool.tsx to import these symbols instead of redefining them; ensure
TypeScript types and any CSS/class names remain unchanged and run a build to fix
any import paths or named export mismatches.
- Around line 117-123: The catch block in the copyRaw function swallowing errors
should be replaced to accept the error (e) and log it (e.g., console.error or
the project logger) so clipboard failures are visible; update the try/catch
around navigator.clipboard.writeText(JSON.stringify(data, null, 2)) to catch
(err) and call console.error("copyRaw: failed to write clipboard", err) (while
leaving setCopied behavior intact).
- Around line 59-62: The catch block in downloadJSON is silently swallowing
errors; update the catch (e) block in the downloadJSON function to log the error
(e.g., console.error or the app logger) with a clear message and the error
object/stack so failures are visible during debugging (include context like
"downloadJSON failed" and stringify or log e.stack where available).

In `@src/components/ai-elements/tools/site-map-extractor-tool.tsx`:
- Around line 40-71: The code is using unsafe "as any" casts for input/output
before destructuring and reducing (see variables output, input, pages,
totalPages and function/component SiteMapExtractorUITool); replace these with a
proper typed output shape or add a runtime shape guard: define an interface for
the tool output (e.g., { pages: Array<{ depth: number; url: string; ... }>;
totalPages: number }) and update SiteMapExtractorUITool's generics/props to use
it, or add a local guard function/type predicate that verifies output is an
object with pages array and numeric totalPages (and that each page has depth)
before doing const { pages, totalPages } = output and pages.reduce; fail fast or
render an error UI when the guard fails instead of casting to any.
- Around line 84-90: The Depth badge currently computes
Math.max(...pages.map((p: typeof pages[number]) => p.depth)) which yields
-Infinity when pages is empty; update the computation in the component that
renders totalPages and pages (the Depth Badge) to provide a safe fallback (e.g.,
compute maxDepth = pages.length ? Math.max(...pages.map(p => p.depth)) : 0 or
use Math.max(0, ...mappedDepths)) and render maxDepth instead so an empty pages
array renders a sensible depth value instead of -Infinity.

In `@src/components/ai-elements/tools/web-scraper-tool.tsx`:
- Around line 67-93: The UI assumes output.content.extractedData exists and uses
extractedData.length and .map, which will throw if undefined; in
src/components/ai-elements/tools/web-scraper-tool.tsx update the destructuring
of content (where extractedData, rawContent, markdownContent are pulled) to
default extractedData to an empty array (e.g., const { extractedData = [],
rawContent, markdownContent } = content) and then use that extractedData when
rendering the count and mapping (references: extractedData, (output as
any).content, and the code that renders Badge and any .map over extractedData)
so the component safely renders when extractedData is missing.

In `@src/mastra/a2a/a2aCoordinatorAgent.ts`:
- Line 1: The import for GoogleGenerativeAIProviderOptions is only used as a
type and should be changed to a type-only import to avoid runtime import
emission; update the top-level import statement that currently references
GoogleGenerativeAIProviderOptions (in src/mastra/a2a/a2aCoordinatorAgent.ts) to
use an import type form so the symbol GoogleGenerativeAIProviderOptions is
imported only for typing.

In `@src/mastra/a2a/codingA2ACoordinator.ts`:
- Line 11: The import of GoogleGenerativeAIProviderOptions is only used as a
type, so change the runtime import to a type-only import; replace the existing
import statement that brings in GoogleGenerativeAIProviderOptions with an
`import type { GoogleGenerativeAIProviderOptions } from '@ai-sdk/google'` to
avoid runtime import overhead and follow the project's type-only import
guideline—update the import where GoogleGenerativeAIProviderOptions is
referenced in codingA2ACoordinator.ts.

In `@src/mastra/agents/businessLegalAgents.ts`:
- Around line 71-75: Change the typed context for the legalResearchAgent
callbacks: replace RequestContext<unknown> with
RequestContext<BusinessRuntimeContext> in both the instructions and model
callback signatures (the functions referenced as instructions and model in
legalResearchAgent) to avoid unsafe casts; mirror the pattern used by
contractAnalysisAgent and update any downstream parameter usages accordingly so
no as any casts are required. Also remove the commented-out pgQueryTool line
near the legalResearchAgent definition to comply with the no-commented-code
guideline.

In `@src/utils/streamUtils.ts`:
- Around line 101-103: Replace the use of `any` in the public `streamResult`
union by introducing a type parameter for the stream payload (e.g., add a
generic like `TStream` or `TResult` with a safe default such as `unknown`) and
use that instead of `any` in `StreamTextResult<ToolSet, any>` so the union
becomes `StreamTextResult<ToolSet, TStream>` | { textStream:
AsyncIterable<string> } (and update the `StreamTextResult` declaration to accept
the new generic). Ensure the exported API signatures that reference
`streamResult` and the `StreamTextResult` type are updated to propagate or
default the new generic type so callers remain type-safe without breaking
compatibility; update any call sites to pass or rely on the default generic
where necessary.
♻️ Duplicate comments (1)
src/components/ai-elements/tools/calculator-tool.tsx (1)

30-78: Duplicate helper functions.

As noted in execa-tool.tsx, ErrorCard, LoadingCard, and downloadFile are duplicated here. Extract to a shared module.

@@ -1,9 +1,48 @@
'use client'
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion | 🟠 Major

Add the required TSDoc file header.

TS/TSX files should include a TSDoc header with @fileoverview, @author, @copyright,
and @license tags. Place it above the 'use client' directive.

🤖 Prompt for AI Agents
In `@app/components/landing-hero.tsx` at line 1, Add a TSDoc file header block
above the existing 'use client' directive in this file: include `@fileoverview`
with a short description, `@author` with the author name, `@copyright` with
year/owner, and `@license` with the project's license identifier; ensure the
header is a proper multi-line TSDoc comment placed immediately before the 'use
client' line so tooling picks it up.

Comment on lines +12 to +44
const heroRef = useRef<HTMLDivElement>(null)

useGSAP(() => {
const tl = gsap.timeline()

// Stagger entrance animation for child elements
tl.fromTo(
'.hero-element',
{ opacity: 0, y: 20 },
{
opacity: 1,
y: 0,
duration: 0.6,
ease: 'power2.out',
stagger: 0.1,
}
)

// Add ScrollTrigger for parallax effect
ScrollTrigger.create({
trigger: heroRef.current,
start: 'top bottom',
end: 'bottom top',
scrub: 1,
onUpdate: (self) => {
const progress = self.progress
gsap.set(heroRef.current, {
y: -progress * 50, // Parallax effect
scale: 1 + progress * 0.05, // Slight zoom
})
},
})
})
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

find . -name "landing-hero.tsx" -type f

Repository: ssdeanx/AgentStack

Length of output: 95


🏁 Script executed:

cat -n app/components/landing-hero.tsx | head -60

Repository: ssdeanx/AgentStack

Length of output: 2758


🌐 Web query:

useGSAP hook scope dependencies cleanup ScrollTrigger best practices

💡 Result:

Here are concise best-practices for a React useGSAP (or gsap.context) hook: scope, deps, and cleanup — with sources.

  1. Prefer gsap.context / useGSAP (not raw global gsap calls)
  • gsap.context collects animations & ScrollTriggers and optionally scopes selectors to a ref so cleanup is trivial. Use the context wrapper for all animations created during render. [1]
  1. Where to run — useLayoutEffect (or the provided useGSAP)
  • Create the context inside useLayoutEffect (or useGSAP which wraps the effect) so layout measurements are stable and React StrictMode double-invocations are handled. [1][5]
  1. Scoping selectors
  • Pass a DOM element or ref to gsap.context (or use the hook’s scope option) so selector strings apply only to descendants and you avoid many refs. [1][6]
  1. Dependencies and updates
  • Treat useGSAP’s second arg (or your internal useLayoutEffect deps) like useEffect deps: list values that should re-run the animation (or set revertOnUpdate if you want the previous context reverted on dependency change). If you need to avoid stale closures, pass reactive values as arguments to event/callbacks or use React patterns (useCallback/useEffectEvent) rather than omitting deps. [6][3]
  1. Cleanup / killing ScrollTriggers
  • Always revert the context on unmount (ctx.revert()). That reverts/kills animations and ScrollTriggers created inside the context. For ScrollTrigger instances you explicitly created and need custom behavior, you can call their kill(revert, allowAnimation) or use ScrollTrigger.clearScrollMemory as needed. [1][2][7]
  1. Animations created after initial context run
  • Animations created later (e.g., in event handlers, setTimeout, async callbacks) are not automatically in the context unless you add them via ctx.add(...) or wrap their creation inside ctx.add / ctx.method so they’ll be reverted/cleaned. Use ctx.add or ctx.add("name", fn) for event-driven animations. [1]
  1. Avoid memory leaks & stale DOM
  • Remove any non-GSAP listeners in the cleanup returned by the context (you can return a cleanup function from the context). If you re-create contexts on dep changes, consider revertOnUpdate or call ctx.revert() before creating a new context to avoid duplicated ScrollTriggers. [1]
  1. ScrollTrigger specifics
  • If you disable or want temporary behavior use ScrollTrigger.disable(); to fully remove instance use .kill(). Be mindful of pin-related DOM changes (use kill(revert) appropriately). If routing/refresh issues arise, consider ScrollTrigger.clearScrollMemory(). Also call ScrollTrigger.refresh() after DOM/layout changes if necessary. [2][4][7]
  1. Practical notes
  • Keep animation logic inside the context function or add it to the context; avoid creating GSAP timelines on every render. Use refs/state only as deps. Test in StrictMode. [1][5]

Sources

  • GSAP docs: gsap.context (useGSAP hook info), including scoping, ctx.add, ctx.revert. [1]
  • ScrollTrigger docs: .kill(), plugin guidance and APIs. [2][4]
  • Practical React/useGSAP guides & examples (community writeups explaining revertOnUpdate/useGSAP behavior). [6][5]

If you want, I can: a) show a minimal React + useGSAP example with proper deps and cleanup, or b) review your component code and point out issues. Which would you prefer?


Scope GSAP selectors, ensure single run, and clean up ScrollTrigger on unmount.

useGSAP() without dependencies or scope options reruns on every render, creating duplicate timelines and ScrollTriggers. The .hero-element selector is global and will animate all matching elements on the page, not just those within this component. Add a null guard, scope the context to heroRef to restrict selectors to descendants, set empty dependencies to run once, and explicitly clean up animations and ScrollTriggers on unmount.

Proposed fix
-    useGSAP(() => {
-        const tl = gsap.timeline()
+    useGSAP(() => {
+        if (!heroRef.current) return
+        const tl = gsap.timeline()
 
         // Stagger entrance animation for child elements
         tl.fromTo(
             '.hero-element',
             { opacity: 0, y: 20 },
             {
                 opacity: 1,
                 y: 0,
                 duration: 0.6,
                 ease: 'power2.out',
                 stagger: 0.1,
             }
         )
 
         // Add ScrollTrigger for parallax effect
-        ScrollTrigger.create({
+        const trigger = ScrollTrigger.create({
             trigger: heroRef.current,
             start: 'top bottom',
             end: 'bottom top',
             scrub: 1,
             onUpdate: (self) => {
                 const progress = self.progress
                 gsap.set(heroRef.current, {
                     y: -progress * 50, // Parallax effect
                     scale: 1 + progress * 0.05, // Slight zoom
                 })
             },
         })
-    })
+        return () => {
+            tl.kill()
+            trigger.kill()
+        }
+    }, { scope: heroRef, dependencies: [] })
📝 Committable suggestion

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

Suggested change
const heroRef = useRef<HTMLDivElement>(null)
useGSAP(() => {
const tl = gsap.timeline()
// Stagger entrance animation for child elements
tl.fromTo(
'.hero-element',
{ opacity: 0, y: 20 },
{
opacity: 1,
y: 0,
duration: 0.6,
ease: 'power2.out',
stagger: 0.1,
}
)
// Add ScrollTrigger for parallax effect
ScrollTrigger.create({
trigger: heroRef.current,
start: 'top bottom',
end: 'bottom top',
scrub: 1,
onUpdate: (self) => {
const progress = self.progress
gsap.set(heroRef.current, {
y: -progress * 50, // Parallax effect
scale: 1 + progress * 0.05, // Slight zoom
})
},
})
})
const heroRef = useRef<HTMLDivElement>(null)
useGSAP(() => {
if (!heroRef.current) return
const tl = gsap.timeline()
// Stagger entrance animation for child elements
tl.fromTo(
'.hero-element',
{ opacity: 0, y: 20 },
{
opacity: 1,
y: 0,
duration: 0.6,
ease: 'power2.out',
stagger: 0.1,
}
)
// Add ScrollTrigger for parallax effect
const trigger = ScrollTrigger.create({
trigger: heroRef.current,
start: 'top bottom',
end: 'bottom top',
scrub: 1,
onUpdate: (self) => {
const progress = self.progress
gsap.set(heroRef.current, {
y: -progress * 50, // Parallax effect
scale: 1 + progress * 0.05, // Slight zoom
})
},
})
return () => {
tl.kill()
trigger.kill()
}
}, { scope: heroRef, dependencies: [] })
🤖 Prompt for AI Agents
In `@app/components/landing-hero.tsx` around lines 12 - 44, Scope the GSAP
animation to this component, guard against a null ref, run the effect only once,
and clean up ScrollTrigger on unmount: wrap the timeline and selector usage in a
gsap.context tied to heroRef (use context.selector or context() so
'.hero-element' targets only descendants), add a null check for heroRef.current
before creating ScrollTrigger, pass an empty dependency array to useGSAP to
ensure a single run, and return a cleanup that kills the timeline/context and
calls ScrollTrigger.getAll()/kill() or kills the specific ScrollTrigger instance
created (reference the ScrollTrigger returned from ScrollTrigger.create) to
remove listeners when the component unmounts.

Comment on lines +1 to +4
<!-- AGENTS-META {"title":"Agent Tools UI Components","version":"1.0.0","last_updated":"2025-01-09T12:00:00Z","applies_to":"/src/components/ai-elements/tools","tags":["layer:frontend","domain:ui","type:components","status:stable"],"status":"stable"} -->

# Tools Directory (`/src/components/ai-elements/tools`)

Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Add required YAML front matter and avoid H1 headings.
Docs guidelines require YAML front matter with the specified fields, and disallow H1. Replace the current meta comment with front matter (keep the AGENTS-META comment if still needed) and demote the heading to ##.

🧾 Example front matter + heading fix
-<!-- AGENTS-META {"title":"Agent Tools UI Components","version":"1.0.0","last_updated":"2025-01-09T12:00:00Z","applies_to":"/src/components/ai-elements/tools","tags":["layer:frontend","domain:ui","type:components","status:stable"],"status":"stable"} -->
-
-# Tools Directory (`/src/components/ai-elements/tools`)
+---
+post_title: "Agent Tools UI Components"
+author1: "TBD"
+post_slug: "agent-tools-ui-components"
+microsoft_alias: "TBD"
+featured_image: "TBD"
+categories: ["TBD"]
+tags: ["layer:frontend", "domain:ui", "type:components", "status:stable"]
+ai_note: "TBD"
+summary: "TBD"
+post_date: "2025-01-09"
+---
+<!-- AGENTS-META {"title":"Agent Tools UI Components","version":"1.0.0","last_updated":"2025-01-09T12:00:00Z","applies_to":"/src/components/ai-elements/tools","tags":["layer:frontend","domain:ui","type:components","status:stable"],"status":"stable"} -->
+
+## Tools Directory (`/src/components/ai-elements/tools`)
📝 Committable suggestion

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

Suggested change
<!-- AGENTS-META {"title":"Agent Tools UI Components","version":"1.0.0","last_updated":"2025-01-09T12:00:00Z","applies_to":"/src/components/ai-elements/tools","tags":["layer:frontend","domain:ui","type:components","status:stable"],"status":"stable"} -->
# Tools Directory (`/src/components/ai-elements/tools`)
---
post_title: "Agent Tools UI Components"
author1: "TBD"
post_slug: "agent-tools-ui-components"
microsoft_alias: "TBD"
featured_image: "TBD"
categories: ["TBD"]
tags: ["layer:frontend", "domain:ui", "type:components", "status:stable"]
ai_note: "TBD"
summary: "TBD"
post_date: "2025-01-09"
---
<!-- AGENTS-META {"title":"Agent Tools UI Components","version":"1.0.0","last_updated":"2025-01-09T12:00:00Z","applies_to":"/src/components/ai-elements/tools","tags":["layer:frontend","domain:ui","type:components","status:stable"],"status":"stable"} -->
## Tools Directory (`/src/components/ai-elements/tools`)
🤖 Prompt for AI Agents
In `@src/components/ai-elements/tools/AGENTS.md` around lines 1 - 4, Replace the
HTML meta comment with proper YAML front matter containing the fields title,
version, last_updated, applies_to, tags, and status (you may retain the existing
AGENTS-META HTML comment above or below it if desired), and change the top-level
H1 heading (“# Tools Directory…”) to an H2 (“## Tools Directory…”) so the file
conforms to docs guidelines; ensure the YAML keys match the values in the
AGENTS-META block (title, version, last_updated, applies_to, tags, status) and
remove the leading H1 syntax.

Loader2,
Search,
} from 'lucide-react'
import { useEffect, useRef, useState, type ChangeEvent } from 'react'
Copy link

Choose a reason for hiding this comment

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

🧹 Nitpick | 🔵 Trivial

Remove unused imports.

useEffect and useRef are imported but not used in this file.

🧹 Proposed fix
-import { useEffect, useRef, useState, type ChangeEvent } from 'react'
+import { useState, type ChangeEvent } from 'react'
📝 Committable suggestion

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

Suggested change
import { useEffect, useRef, useState, type ChangeEvent } from 'react'
import { useState, type ChangeEvent } from 'react'
🤖 Prompt for AI Agents
In `@src/components/ai-elements/tools/browser-tool.tsx` at line 30, The import
statement includes unused symbols useEffect and useRef; remove them from the
import so only used symbols (useState and type ChangeEvent if used) remain.
Update the import line that currently mentions useEffect and useRef to only
import the actually used hooks/types (e.g., ensure useState and ChangeEvent are
kept if referenced elsewhere in this module such as in the BrowserTool
component), and run a quick build or linter to confirm no missing imports
remain.

Comment on lines +64 to +67
} catch {
// ignore
}
}
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Avoid silent failure—log or surface the error.

Silently ignoring errors makes debugging difficult. Consider logging the error or providing user feedback. As per coding guidelines, avoid silent failures.

🐛 Proposed fix
   } catch {
-    // ignore
+    console.error('Failed to download file from base64')
   }
📝 Committable suggestion

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

Suggested change
} catch {
// ignore
}
}
} catch {
console.error('Failed to download file from base64')
}
}
🤖 Prompt for AI Agents
In `@src/components/ai-elements/tools/browser-tool.tsx` around lines 64 - 67, The
empty catch in src/components/ai-elements/tools/browser-tool.tsx silently
swallows errors; change the catch to capture the exception (catch (err)) and log
it and/or surface it to the user (e.g., use existing logger or console.error and
update local state or call an error handler) inside the BrowserTool handler
where the catch sits so failures are visible for debugging and the UI can show
an error message or fallback behavior.

Comment on lines +67 to +93
const content = (output as any).content || {}
const {
extractedData,
rawContent,
markdownContent,
} = content

const {
metadata,
images,
structuredData,
} = output.analysis || {}
const {
metadata,
images,
} = (output as any).analysis || {}

return (
<div className="space-y-4">
{/* Success Header */}
<Card className="border-green-500/20 bg-green-500/5">
<CardHeader className="pb-3">
<CardTitle className="flex items-center gap-2 text-sm">
<Globe className="size-4 text-green-600" />
Successfully scraped {output.url}
</CardTitle>
</CardHeader>
<CardContent>
<div className="flex items-center gap-4 text-sm">
<Badge variant="secondary" className="text-green-700">
{extractedData.length} elements extracted
</Badge>
{markdownContent && (
<Badge
variant="secondary"
className="text-blue-700"
>
<FileText className="size-3 mr-1" />
Markdown generated
</Badge>
)}
{images && images.length > 0 && (
<Badge
variant="secondary"
className="text-purple-700"
>
<ImageIcon className="size-3 mr-1" />
{images.length} images found
</Badge>
)}
</div>
</CardContent>
</Card>
return (
<div className="space-y-4">
{/* Success Header */}
<Card className="border-green-500/20 bg-green-500/5">
<CardHeader className="pb-3">
<CardTitle className="flex items-center gap-2 text-sm">
<Globe className="size-4 text-green-600" />
Successfully scraped {(output as any).url}
</CardTitle>
</CardHeader>
<CardContent>
<div className="flex items-center gap-4 text-sm">
<Badge variant="secondary" className="text-green-700">
{extractedData.length} elements extracted
</Badge>
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Guard against missing extractedData.
If output.content.extractedData is undefined, extractedData.length/.map will throw. Default to an empty array.

✅ Safer defaults
-  const { extractedData, rawContent, markdownContent } = content
+  const extractedData = Array.isArray(content.extractedData)
+    ? content.extractedData
+    : []
+  const { rawContent, markdownContent } = content
🤖 Prompt for AI Agents
In `@src/components/ai-elements/tools/web-scraper-tool.tsx` around lines 67 - 93,
The UI assumes output.content.extractedData exists and uses extractedData.length
and .map, which will throw if undefined; in
src/components/ai-elements/tools/web-scraper-tool.tsx update the destructuring
of content (where extractedData, rawContent, markdownContent are pulled) to
default extractedData to an empty array (e.g., const { extractedData = [],
rawContent, markdownContent } = content) and then use that extractedData when
rendering the count and mapping (references: extractedData, (output as
any).content, and the code that renders Badge and any .map over extractedData)
so the component safely renders when extractedData is missing.

@@ -1,26 +1,26 @@
import { GoogleGenerativeAIProviderOptions } from '@ai-sdk/google'
Copy link

Choose a reason for hiding this comment

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

🧹 Nitpick | 🔵 Trivial

Use a type-only import for GoogleGenerativeAIProviderOptions.

It’s only used in type positions; import type avoids runtime import emission. As per coding guidelines, use type-only imports for type declarations.

♻️ Proposed change
-import { GoogleGenerativeAIProviderOptions } from '@ai-sdk/google'
+import type { GoogleGenerativeAIProviderOptions } from '@ai-sdk/google'
🤖 Prompt for AI Agents
In `@src/mastra/a2a/a2aCoordinatorAgent.ts` at line 1, The import for
GoogleGenerativeAIProviderOptions is only used as a type and should be changed
to a type-only import to avoid runtime import emission; update the top-level
import statement that currently references GoogleGenerativeAIProviderOptions (in
src/mastra/a2a/a2aCoordinatorAgent.ts) to use an import type form so the symbol
GoogleGenerativeAIProviderOptions is imported only for typing.

import { log } from '../config/logger'
import { pgMemory } from '../config/pg-storage'

import { GoogleGenerativeAIProviderOptions } from '@ai-sdk/google'
Copy link

Choose a reason for hiding this comment

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

🧹 Nitpick | 🔵 Trivial

Use a type-only import for provider options.

GoogleGenerativeAIProviderOptions is only used as a type; import type prevents any runtime import overhead. As per coding guidelines, use type-only imports for type declarations.

♻️ Proposed change
-import { GoogleGenerativeAIProviderOptions } from '@ai-sdk/google'
+import type { GoogleGenerativeAIProviderOptions } from '@ai-sdk/google'
🤖 Prompt for AI Agents
In `@src/mastra/a2a/codingA2ACoordinator.ts` at line 11, The import of
GoogleGenerativeAIProviderOptions is only used as a type, so change the runtime
import to a type-only import; replace the existing import statement that brings
in GoogleGenerativeAIProviderOptions with an `import type {
GoogleGenerativeAIProviderOptions } from '@ai-sdk/google'` to avoid runtime
import overhead and follow the project's type-only import guideline—update the
import where GoogleGenerativeAIProviderOptions is referenced in
codingA2ACoordinator.ts.

Comment on lines 71 to 75
instructions: ({
requestContext,
}: {
requestContext: RequestContext<BusinessRuntimeContext>
requestContext: RequestContext<unknown>
}) => {
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

git ls-files src/mastra/agents/ | head -20

Repository: ssdeanx/AgentStack

Length of output: 814


🏁 Script executed:

wc -l src/mastra/agents/businessLegalAgents.ts

Repository: ssdeanx/AgentStack

Length of output: 106


🏁 Script executed:

cat -n src/mastra/agents/businessLegalAgents.ts | sed -n '65,85p'

Repository: ssdeanx/AgentStack

Length of output: 921


🏁 Script executed:

cat -n src/mastra/agents/businessLegalAgents.ts | sed -n '125,145p'

Repository: ssdeanx/AgentStack

Length of output: 791


🏁 Script executed:

# Search for BusinessRuntimeContext definition
fd . src/mastra --type f \( -name "*.ts" -o -name "*.tsx" \) | xargs grep -l "BusinessRuntimeContext" | head -10

Repository: ssdeanx/AgentStack

Length of output: 292


🏁 Script executed:

# Search for RequestContext usage patterns
rg "RequestContext<" src/mastra/agents/ -A 2 -B 2

Repository: ssdeanx/AgentStack

Length of output: 21705


🏁 Script executed:

# Check for commented-out pgQueryTool references
rg "pgQueryTool" src/mastra/agents/businessLegalAgents.ts -B 2 -A 2

Repository: ssdeanx/AgentStack

Length of output: 692


🏁 Script executed:

# Check what agents in this file use BusinessRuntimeContext
grep -n "RequestContext<BusinessRuntimeContext>" src/mastra/agents/businessLegalAgents.ts | head -10

Repository: ssdeanx/AgentStack

Length of output: 250


🏁 Script executed:

# Find where BusinessRuntimeContext is defined
rg "type BusinessRuntimeContext|interface BusinessRuntimeContext" src/mastra/agents/ -B 2 -A 5

Repository: ssdeanx/AgentStack

Length of output: 612


🏁 Script executed:

# Get more context around the legalResearchAgent tools definition
cat -n src/mastra/agents/businessLegalAgents.ts | sed -n '95,115p'

Repository: ssdeanx/AgentStack

Length of output: 1349


🏁 Script executed:

# Check the full tools array for legalResearchAgent
cat -n src/mastra/agents/businessLegalAgents.ts | sed -n '90,122p'

Repository: ssdeanx/AgentStack

Length of output: 2202


🏁 Script executed:

# Check what requestContext.get() calls are made in legalResearchAgent
cat -n src/mastra/agents/businessLegalAgents.ts | sed -n '71,130p'

Repository: ssdeanx/AgentStack

Length of output: 3319


🏁 Script executed:

# Check the imports at the top of the file
head -60 src/mastra/agents/businessLegalAgents.ts | tail -30

Repository: ssdeanx/AgentStack

Length of output: 811


🏁 Script executed:

# Check if there are other agents in this file that use BusinessRuntimeContext correctly
cat -n src/mastra/agents/businessLegalAgents.ts | sed -n '195,210p'

Repository: ssdeanx/AgentStack

Length of output: 735


🏁 Script executed:

# Check the model function signature at line 133-137
cat -n src/mastra/agents/businessLegalAgents.ts | sed -n '130,150p'

Repository: ssdeanx/AgentStack

Length of output: 685


Use RequestContext<BusinessRuntimeContext> for both instructions and model callbacks in legalResearchAgent.

RequestContext<unknown> requires unsafe as any casts (lines 93–94) and breaks compile-time type safety. BusinessRuntimeContext is defined in this file and already used correctly in contractAnalysisAgent. Align with the codebase pattern where all agents use typed contexts to enforce access control.

Also remove the commented-out pgQueryTool (line ~109) per the guideline against commented code.

🤖 Prompt for AI Agents
In `@src/mastra/agents/businessLegalAgents.ts` around lines 71 - 75, Change the
typed context for the legalResearchAgent callbacks: replace
RequestContext<unknown> with RequestContext<BusinessRuntimeContext> in both the
instructions and model callback signatures (the functions referenced as
instructions and model in legalResearchAgent) to avoid unsafe casts; mirror the
pattern used by contractAnalysisAgent and update any downstream parameter usages
accordingly so no as any casts are required. Also remove the commented-out
pgQueryTool line near the legalResearchAgent definition to comply with the
no-commented-code guideline.

Comment on lines 101 to 103
streamResult:
| StreamTextResult<ToolSet, unknown>
| StreamTextResult<ToolSet, any>
| { textStream: AsyncIterable<string> },
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion | 🟠 Major

Avoid any in the public API; keep type safety.

Using any here defeats type checking and conflicts with the “no explicit any” guideline. Consider a generic parameter with a safe default instead.

♻️ Proposed change
-export async function handleTextStream(
-    streamResult:
-        | StreamTextResult<ToolSet, any>
-        | { textStream: AsyncIterable<string> },
+export async function handleTextStream<TStream = unknown>(
+    streamResult:
+        | StreamTextResult<ToolSet, TStream>
+        | { textStream: AsyncIterable<string> },
📝 Committable suggestion

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

Suggested change
streamResult:
| StreamTextResult<ToolSet, unknown>
| StreamTextResult<ToolSet, any>
| { textStream: AsyncIterable<string> },
export async function handleTextStream<TStream = unknown>(
streamResult:
| StreamTextResult<ToolSet, TStream>
| { textStream: AsyncIterable<string> },
🤖 Prompt for AI Agents
In `@src/utils/streamUtils.ts` around lines 101 - 103, Replace the use of `any` in
the public `streamResult` union by introducing a type parameter for the stream
payload (e.g., add a generic like `TStream` or `TResult` with a safe default
such as `unknown`) and use that instead of `any` in `StreamTextResult<ToolSet,
any>` so the union becomes `StreamTextResult<ToolSet, TStream>` | { textStream:
AsyncIterable<string> } (and update the `StreamTextResult` declaration to accept
the new generic). Ensure the exported API signatures that reference
`streamResult` and the `StreamTextResult` type are updated to propagate or
default the new generic type so callers remain type-safe without breaking
compatibility; update any call sites to pass or rely on the default generic
where necessary.

@ssdeanx ssdeanx merged commit acf1928 into main Jan 16, 2026
377 of 382 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants