Skip to content

Conversation

@techwithanirudh
Copy link
Owner

@techwithanirudh techwithanirudh commented Jun 18, 2025

…g in Discord

Summary by CodeRabbit

  • New Features

    • Added a slash command for AI chat interaction within Discord.
    • Introduced web search capability using ExaAI, accessible via a new tool.
    • Added a new environment variable for ExaAI integration.
    • New spelling and formatting checks, commit linting, and pre-commit hooks for improved code quality.
    • Added a project funding file and a pull request template for contributors.
  • Improvements

    • Enhanced AI prompts to always include spelling and grammatical mistakes for a more human-like response.
    • Expanded configuration and validation for environment variables.
    • Updated initial messages and configuration for a more conversational tone.
    • Improved type safety and error handling in utility functions.
    • Refined and grouped import statements for better code organization.
  • Chores

    • Introduced and updated configuration files for spell checking, linting, and code ownership.
    • Updated the TODO list with new tasks and progress.
  • Bug Fixes

    • Improved runtime type checking and error handling in various utilities.
  • Refactor

    • Updated function signatures and types for broader compatibility and maintainability.
    • Disabled registration for certain voice channel commands.
  • Style

    • Reorganized import statements and export orders for consistency.

… quality and organization

- Added `import-x` plugin and TypeScript resolver to ESLint configuration.
- Updated dependencies in `package.json` and `bun.lock` for ESLint and Prettier plugins.
- Refactored imports in `discord.ts` and `stream.ts` for better organization and clarity.
…ty and consistency

- Adjusted import statements in `deploy-commands.ts`, `index.ts`, and various command files to enhance readability.
- Ensured consistent ordering of imports in `message-create` event handlers and utility files.
- Removed redundant imports and streamlined code structure in several modules.
…ell checking

- Corrected spelling for "ASSEMBLYAI" to "assemblyai" and "ELEVENLABS" to "ElevenLabs".
- Added new entries "HackClub" and "OpenRouter" to the cSpell dictionary.
…ence

- Commented out the `hackclub`, `openrouter`, and `google` provider configurations in `providers.ts` to prevent unused code while maintaining the option to re-enable them later.
…ders.ts

- Removed unused import statements for `env`, `createGoogleGenerativeAI`, `createOpenAICompatible`, and `createOpenRouter` to clean up the code and improve maintainability.
@coderabbitai
Copy link

coderabbitai bot commented Jun 18, 2025

Walkthrough

This update introduces a web search feature using ExaAI, adds a new slash command for chat, and integrates a web search tool into the AI assistant. The changes include new and updated environment variables, configuration files, stricter linting and commit message standards, expanded prompts, improved type safety, and refactored tool and context handling.

Changes

File(s) / Path(s) Change Summary
.cspell.json, .github/CODEOWNERS, .github/FUNDING.yml, .github/pull-request-template.md, .husky/commit-msg, .husky/pre-commit, commitlint.config.ts Added configuration files for spell checking, code ownership, funding, PR templates, commit hooks, and commit linting.
.env.example, src/env.ts Added EXA_API_KEY for ExaAI web search; updated URL validation for Redis.
.eslintignore, .eslintrc.json, package.json Updated ESLint, Prettier, and linting configurations; added new scripts and dependencies for linting, formatting, commit linting, and spell checking.
.vscode/settings.json Removed workspace spell checker settings (custom words).
TODO.md Updated and expanded project TODOs; marked some items as done.
src/commands/chat.ts, src/commands/index.ts Added new "chat" slash command and registered it.
src/commands/channels.ts, src/commands/voice-channel/index.ts, src/commands/voice-channel/join.ts, src/commands/voice-channel/leave.ts Reorganized imports; commented out voice join/leave command registration.
src/config.ts Updated initialMessages typing/content; increased speed factor.
src/deploy-commands.ts, src/index.ts, src/lib/logger.ts, src/lib/queries.ts, src/utils/context.ts, src/utils/delay.ts, src/utils/message-rate-limiter.ts, src/utils/status.ts, src/utils/time.ts, src/utils/voice/helpers/ai.ts, src/utils/voice/helpers/audio.ts, src/utils/voice/helpers/index.ts, src/utils/voice/stream.ts, src/events/message-create/index.ts, src/events/message-create/utils/relevance.ts Reordered imports and/or exports for clarity and style.
src/events/message-create/utils/respond.ts Refactored to use generic MinimalContext, conditional tool inclusion, added web search tool, improved options handling.
src/lib/ai/prompts.ts Strengthened prompt instructions to always include spelling/grammar mistakes; added searchWeb and getWeather tool descriptions.
src/lib/ai/providers.ts Cleaned up imports; updated model invocation to use responses method.
src/lib/ai/tools/discord.ts, src/utils/sandbox.ts Improved type annotations (anyunknown), enhanced error handling.
src/lib/ai/tools/report.ts Changed function parameter from Message to MinimalContext.
src/lib/ai/tools/search-web.ts, src/lib/search.ts Added new web search tool and ExaAI client integration.
src/utils/discord.ts Changed function parameter type from any to unknown.
src/utils/messages.ts Added MinimalContext type and isDiscordMessage type guard.
src/utils/context.ts Changed context builder to use MinimalContext.

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant DiscordBot
    participant ExaAI
    participant AI_Assistant

    User->>DiscordBot: Uses /chat slash command with prompt
    DiscordBot->>AI_Assistant: Builds context (with MinimalContext)
    AI_Assistant->>ExaAI: (If needed) Calls searchWeb tool with query
    ExaAI-->>AI_Assistant: Returns web search results
    AI_Assistant-->>DiscordBot: Generates reply (may include search results)
    DiscordBot-->>User: Sends response message
Loading

Possibly related PRs

Poem

In the warren of code, a new search appears,
ExaAI hops in, dispelling old fears.
With slash commands fresh and spelling checked twice,
The bot now responds with errors—how nice!
Linting is stricter, the prompts are more fun,
This rabbit’s delighted—what a great run!
🐇✨

✨ Finishing Touches
  • 📝 Generate Docstrings
🧪 Generate Unit Tests
  • Create PR with Unit Tests
  • Post Copyable Unit Tests in Comment
  • Commit Unit Tests in branch feat/personification

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

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

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

Support

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

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai auto-generate unit tests to generate unit tests for this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

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

CodeRabbit Configuration File (.coderabbit.yaml)

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

Documentation and Community

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

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: 26

🔭 Outside diff range comments (5)
src/utils/time.ts (1)

1-10: TZDate is a type, not a runtime constructor – this will crash at runtime

@date-fns/tz exports TZDate only as a TypeScript type alias.
new TZDate() fails because no value with that name exists at runtime.

-import { TZDate } from '@date-fns/tz';
-import { format } from 'date-fns';
+import { formatInTimeZone } from 'date-fns-tz';
export function getTimeInCity(
  timezone: string,
  formatStr = 'yyyy-MM-dd HH:mm:ssXXX',
): string {
-  const now = new Date();
-  const zonedDate = new TZDate(now, timezone);
-  return format(zonedDate, formatStr);
+  return formatInTimeZone(new Date(), timezone, formatStr);
}

This removes the invalid constructor call while keeping the same public API.

src/index.ts (1)

41-50: Unhandled promise & suppressed type errors

commands[commandName …].execute(interaction); is async but not awaited and errors will bubble to the global handler, potentially crashing the bot.

Coupled with the // @ts-expect-error, you’re actively hiding a structural typing issue.

-client.on(Events.InteractionCreate, async (interaction) => {
+client.on(Events.InteractionCreate, async (interaction) => {
   if (!interaction.isCommand()) {
     return;
   }
   const { commandName } = interaction;
-  if (commands[commandName as keyof typeof commands]) {
-    // @ts-expect-error todo: fix this
-    commands[commandName as keyof typeof commands].execute(interaction);
+  const command = commands[commandName as keyof typeof commands];
+  if (command) {
+    try {
+      await command.execute(interaction);
+    } catch (error) {
+      logger.error(error, `Failed to execute /${commandName}`);
+      if (interaction.replied || interaction.deferred) {
+        await interaction.followUp({ content: 'Something went wrong!', ephemeral: true });
+      } else {
+        await interaction.reply({ content: 'Something went wrong!', ephemeral: true });
+      }
+    }
   }
 });

This removes the suppression, awaits the promise, and surfaces controlled feedback to users.

src/utils/voice/stream.ts (1)

50-62: playAudio is async but not awaited

You now correctly await speak, but playAudio likely returns a promise (stream piping / player subscription). Not awaiting it may resume transcription early and overlap audio.

-        // @ts-expect-error this is a ReadableStream
-        playAudio(player, audio);
+        // @ts-expect-error playAudio returns a promise we intentionally await
+        await playAudio(player, audio);

Also consider resuming player via player.unpause() after playback if simultaneous transcription is desired.

src/commands/voice-channel/join.ts (2)

45-49: Potential listener leak on receiver.speaking

Every execution adds a permanent speaking listener. Re-invoking /join (or simply reloading the bot) will accumulate listeners and duplicate audio processing.

-    receiver.speaking.on('start', async (userId) => {
+    const onSpeaking = async (userId: string) => {
       const user = await interaction.client.users.fetch(userId);
       await createListeningStream(receiver, player, user);
-    });
+    };
+    receiver.speaking.once('start', onSpeaking);
+    connection.once(VoiceConnectionStatus.Destroyed, () =>
+      receiver.speaking.off('start', onSpeaking),
+    );

18-20: Prefer editReply() over the first followUp() after deferReply()

interaction.deferReply() reserves the initial response. Using interaction.editReply() keeps the interaction thread clean and avoids exceeding Discord’s 5-message per-interaction hard limit.

-  await interaction.deferReply();
+  await interaction.deferReply();

...

-    await interaction.followUp(
+    await interaction.editReply(
       "oops, idk what happened. I couldn't join the voice channel.",
     );

...

-  await interaction.followUp('thanks for inviting me! joined');
+  await interaction.editReply('thanks for inviting me! joined');

Also applies to: 52-58

📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 39decc2 and 38ee5bc.

⛔ Files ignored due to path filters (1)
  • bun.lock is excluded by !**/*.lock
📒 Files selected for processing (46)
  • .cspell.json (1 hunks)
  • .env.example (1 hunks)
  • .eslintignore (1 hunks)
  • .eslintrc.json (1 hunks)
  • .github/CODEOWNERS (1 hunks)
  • .github/FUNDING.yml (1 hunks)
  • .github/pull-request-template.md (1 hunks)
  • .husky/commit-msg (1 hunks)
  • .husky/pre-commit (1 hunks)
  • .vscode/settings.json (0 hunks)
  • TODO.md (1 hunks)
  • commitlint.config.ts (1 hunks)
  • package.json (3 hunks)
  • src/commands/channels.ts (1 hunks)
  • src/commands/chat.ts (1 hunks)
  • src/commands/index.ts (1 hunks)
  • src/commands/voice-channel/index.ts (1 hunks)
  • src/commands/voice-channel/join.ts (1 hunks)
  • src/commands/voice-channel/leave.ts (3 hunks)
  • src/config.ts (2 hunks)
  • src/deploy-commands.ts (1 hunks)
  • src/env.ts (1 hunks)
  • src/events/message-create/index.ts (1 hunks)
  • src/events/message-create/utils/relevance.ts (1 hunks)
  • src/events/message-create/utils/respond.ts (2 hunks)
  • src/index.ts (1 hunks)
  • src/lib/ai/prompts.ts (3 hunks)
  • src/lib/ai/providers.ts (1 hunks)
  • src/lib/ai/tools/discord.ts (3 hunks)
  • src/lib/ai/tools/report.ts (1 hunks)
  • src/lib/ai/tools/search-web.ts (1 hunks)
  • src/lib/logger.ts (1 hunks)
  • src/lib/queries.ts (0 hunks)
  • src/lib/search.ts (1 hunks)
  • src/utils/context.ts (1 hunks)
  • src/utils/delay.ts (2 hunks)
  • src/utils/discord.ts (1 hunks)
  • src/utils/message-rate-limiter.ts (1 hunks)
  • src/utils/messages.ts (2 hunks)
  • src/utils/sandbox.ts (4 hunks)
  • src/utils/status.ts (2 hunks)
  • src/utils/time.ts (1 hunks)
  • src/utils/voice/helpers/ai.ts (1 hunks)
  • src/utils/voice/helpers/audio.ts (1 hunks)
  • src/utils/voice/helpers/index.ts (1 hunks)
  • src/utils/voice/stream.ts (2 hunks)
💤 Files with no reviewable changes (2)
  • src/lib/queries.ts
  • .vscode/settings.json
🧰 Additional context used
🧬 Code Graph Analysis (7)
src/lib/search.ts (1)
src/env.ts (1)
  • env (4-58)
src/utils/context.ts (1)
src/utils/messages.ts (1)
  • MinimalContext (10-13)
src/utils/voice/stream.ts (2)
src/utils/voice/helpers/deepgram.ts (1)
  • speak (11-23)
src/config.ts (1)
  • voice (37-39)
src/lib/ai/tools/report.ts (1)
src/utils/messages.ts (1)
  • MinimalContext (10-13)
src/utils/status.ts (1)
src/config.ts (1)
  • activities (16-21)
src/lib/ai/tools/search-web.ts (1)
src/lib/search.ts (1)
  • exa (10-10)
src/events/message-create/utils/respond.ts (4)
src/utils/messages.ts (2)
  • MinimalContext (10-13)
  • isDiscordMessage (67-69)
src/lib/ai/prompts.ts (1)
  • RequestHints (3-12)
src/lib/ai/tools/report.ts (1)
  • report (6-34)
src/lib/ai/tools/discord.ts (1)
  • discord (17-166)
🪛 ESLint
src/lib/ai/tools/discord.ts

[error] 6-6: Unable to resolve path to module 'ai'.

(import-x/no-unresolved)


[error] 8-8: Unable to resolve path to module 'zod/v4'.

(import-x/no-unresolved)

src/events/message-create/utils/relevance.ts

[error] 4-4: Unable to resolve path to module 'ai'.

(import-x/no-unresolved)

src/events/message-create/index.ts

[error] 10-10: Unable to resolve path to module 'discord.js'.

(import-x/no-unresolved)

src/lib/search.ts

[error] 2-2: Unable to resolve path to module 'exa-js'.

(import-x/no-unresolved)

src/deploy-commands.ts

[error] 2-2: Unable to resolve path to module 'discord.js'.

(import-x/no-unresolved)

src/utils/voice/helpers/ai.ts

[error] 3-3: Unable to resolve path to module 'ai'.

(import-x/no-unresolved)

src/utils/context.ts

[error] 6-6: Unable to resolve path to module '@mem0/vercel-ai-provider'.

(import-x/no-unresolved)

src/utils/voice/stream.ts

[error] 3-3: Unable to resolve path to module '@deepgram/sdk'.

(import-x/no-unresolved)


[error] 8-8: Unable to resolve path to module '@discordjs/voice'.

(import-x/no-unresolved)


[error] 10-10: Unable to resolve path to module 'prism-media'.

(import-x/no-unresolved)

src/commands/voice-channel/index.ts

[error] 1-1: Unable to resolve path to module 'discord.js'.

(import-x/no-unresolved)

src/utils/delay.ts

[error] 3-3: Unable to resolve path to module 'discord.js'.

(import-x/no-unresolved)

src/lib/ai/tools/report.ts

[error] 3-3: Unable to resolve path to module 'ai'.

(import-x/no-unresolved)


[error] 4-4: Unable to resolve path to module 'zod/v4'.

(import-x/no-unresolved)

src/utils/time.ts

[error] 2-2: Unable to resolve path to module 'date-fns'.

(import-x/no-unresolved)

src/utils/messages.ts

[error] 8-8: Unable to resolve path to module 'discord.js'.

(import-x/no-unresolved)

src/lib/logger.ts

[error] 5-5: Unable to resolve path to module 'pino'.

(import-x/no-unresolved)

src/lib/ai/providers.ts

[error] 1-1: Unable to resolve path to module 'ai'.

(import-x/no-unresolved)


[error] 3-3: Unable to resolve path to module '@ai-sdk/openai'.

(import-x/no-unresolved)

src/commands/voice-channel/join.ts

[error] 8-8: Unable to resolve path to module '@discordjs/voice'.

(import-x/no-unresolved)

src/commands/voice-channel/leave.ts

[error] 1-1: Unable to resolve path to module '@discordjs/voice'.

(import-x/no-unresolved)

src/utils/status.ts

[error] 4-4: Unable to resolve path to module 'discord.js'.

(import-x/no-unresolved)

src/commands/chat.ts

[error] 8-8: Unable to resolve path to module 'discord.js'.

(import-x/no-unresolved)

src/lib/ai/tools/search-web.ts

[error] 3-3: Unable to resolve path to module 'ai'.

(import-x/no-unresolved)


[error] 4-4: Unable to resolve path to module 'zod/v4'.

(import-x/no-unresolved)

src/events/message-create/utils/respond.ts

[error] 9-9: Unable to resolve path to module '@mem0/vercel-ai-provider'.

(import-x/no-unresolved)


[error] 11-11: Unable to resolve path to module 'ai'.

(import-x/no-unresolved)

src/index.ts

[error] 7-7: Unable to resolve path to module 'discord.js'.

(import-x/no-unresolved)

🪛 dotenv-linter (3.3.0)
.env.example

[warning] 60-60: [EndingBlankLine] No blank line at the end of the file

🪛 LanguageTool
.github/pull-request-template.md

[style] ~9-~9: Consider using a different verb for a more formal wording.
Context: ... [ ] Bug fix (non-breaking change which fixes an issue) - [ ] New feature (non-breaki...

(FIX_RESOLVE)

TODO.md

[uncategorized] ~9-~9: Did you mean “its” (the possessive pronoun)?
Context: ...realistic. Separate Deepgram code into it's files Implement Conversation history fo...

(ITS_PREMIUM)


[style] ~13-~13: The phrasing ‘more easy’ can sound awkward and informal. Consider using a comparative adjective or other alternative.
Context: ...r). Refactor the channels command to be more easy to use, with deny and allow lists. Det...

(MORE_EASY_N_CLEAR)


[typographical] ~15-~15: If specifying a range, consider using an en dash instead of a hyphen.
Context: ...he response before replying fully, wait 1-2 seconds (for one user). This adds dedup...

(HYPHEN_TO_EN)


[uncategorized] ~23-~23: A comma might be missing here.
Context: ...pGram things are kept When the user is typing increase the response speed by 0.5x. Al...

(AI_EN_LECTOR_MISSING_PUNCTUATION_COMMA)


[uncategorized] ~23-~23: A comma might be missing here.
Context: ... 0.5x. Also, use a different method for responding like a set WPM. Add CI/CD testing so p...

(AI_EN_LECTOR_MISSING_PUNCTUATION_COMMA)


[uncategorized] ~25-~25: This verb does not appear to agree with the subject. Consider using a different form.
Context: ...testing so pushing things to production don't break stuff. Add context to when th...

(AI_EN_LECTOR_REPLACEMENT_VERB_AGREEMENT)


[typographical] ~33-~33: Consider adding a comma here.
Context: ...the bot always remembers the same person no matter where they interact with it.

(NO_MATTER_COMMA)

🪛 markdownlint-cli2 (0.17.2)
.github/pull-request-template.md

1-1: First line in a file should be a top-level heading
null

(MD041, first-line-heading, first-line-h1)

🪛 Biome (1.9.4)
src/commands/chat.ts

[error] 36-36: Forbidden non-null assertion.

(lint/style/noNonNullAssertion)

🔇 Additional comments (30)
.eslintignore (1)

2-2: ```shell
#!/bin/bash
cat -n .eslintignore


</details>
<details>
<summary>src/lib/logger.ts (1)</summary>

`2-5`: ```shell
#!/bin/bash
# Check if 'pino' is listed in dependencies or devDependencies in package.json
grep -R '"pino"' -n package.json || true
src/commands/voice-channel/index.ts (1)

1-1: Import reorder is purely stylistic
Swapping the two discord.js imports has no functional impact.

src/utils/voice/helpers/index.ts (1)

2-2: Export order change has no side effects
Moving the audio export after ai is safe and does not affect module resolution.

src/utils/message-rate-limiter.ts (1)

2-2: Import statement reordering is acceptable
Reordering redis and redisKeys below messageThreshold aligns with the project's import grouping convention.

src/utils/voice/helpers/ai.ts (1)

2-3: Maintain import consistency and verify 'ai' resolution
Switching the order of myProvider and generateText is safe. Please confirm that the ai package is installed and correctly configured in your package.json/tsconfig.json.

src/events/message-create/utils/relevance.ts (1)

4-5: Import reorder is fine; check 'ai' module path
Swapping generateObject, ModelMessage and the Discord Message import doesn't affect behavior. Ensure the ai module exists in dependencies and that TypeScript can resolve its types.

src/deploy-commands.ts (1)

2-2: ES Lint is flagging an unresolved discord.js path – double-check your module resolution config

ESLint’s import-x/no-unresolved hint suggests the resolver cannot locate discord.js.
If you’re on ESM + TS with path aliases, ensure:

  1. typescript paths + ts-node/bundler config map discord.js correctly.
  2. eslint-import-resolver-typescript (or Node) is enabled and sees your tsconfig.json.

This avoids false-positive CI failures.

src/utils/discord.ts (1)

72-75: Good move: switching parameter type from any to unknown tightens type safety

The new signature protects callers from accidentally bypassing type checks while retaining the same runtime behaviour.
No further action needed.

.github/FUNDING.yml (1)

1-2: Funding file looks correct

GitHub Sponsors and Buy Me a Coffee entries are properly formatted.

src/index.ts (1)

1-10: discord.js path resolution fails under ESLint

ESLint reports import-x/no-unresolved for 'discord.js'.
If you rely on path aliases (@/…) via tsconfig/eslint-import-resolver-typescript, ensure the resolver also treats bare packages, or pin a type-only import (import type) when running in Bun/Deno environments.

Run the resolver to confirm all bare package imports are recognised:

#!/bin/bash
# List unresolved imports reported by ESLint
eslint --ext .ts src | grep "no-unresolved"
src/events/message-create/index.ts (1)

2-16: Broken module resolution for discord.js & KV libs

ESLint flags import-x/no-unresolved for 'discord.js'. Verify that your paths/moduleResolution in tsconfig.json and the ESLint import resolver are aligned; otherwise CI will keep failing.

If the issue is false-positive (e.g., monorepo hoisting), add the correct resolver config instead of silencing the rule.

src/utils/voice/stream.ts (1)

1-12: Resolve missing peer dependencies

@deepgram/sdk, @discordjs/voice, and prism-media are flagged as unresolved. Ensure they are listed in package.json dependencies, not just devDependencies, or production deployments will break.

src/commands/channels.ts (1)

1-8: Import shuffle looks fine.

Pure re-ordering; no functional or build impact detected.

src/utils/delay.ts (1)

51-53: Removal of .toLowerCase() might break downstream text-matching logic.

Several NLP / regex routines elsewhere may have assumed lower-cased segments (e.g. keyword filters or similarity checks). Verify that preserving the original casing in text does not impact those call-sites.

src/lib/ai/tools/report.ts (1)

1-7: Unresolvable module paths – update imports.

ESLint flags both ai and zod/v4 as unknown. Unless you have path aliases for them, change to the canonical packages:

-import { tool } from 'ai';
-import { z } from 'zod/v4';
+import { tool } from 'ai-js';      // or your actual helper library
+import { z } from 'zod';

Confirm that the build & type-checker run cleanly after adjusting.

src/commands/voice-channel/join.ts (1)

11-13: ```shell
#!/bin/bash

Show src/commands/voice-channel/index.ts to inspect how commands are aggregated

echo "🔍 src/commands/voice-channel/index.ts (first 200 lines):"
sed -n '1,200p' src/commands/voice-channel/index.ts || echo "⚠️ File not found: src/commands/voice-channel/index.ts"

echo

Show root commands index if exists

echo "🔍 src/commands/index.ts (first 200 lines):"
sed -n '1,200p' src/commands/index.ts || echo "⚠️ File not found: src/commands/index.ts"


</details>
<details>
<summary>src/config.ts (2)</summary>

`12-13`: **Tripling `speedFactor` changes response pacing – validate UX**

Raising `speedFactor` from 60 → 180 will cut the typing-simulation delay to one-third (because delay = tokens / speedFactor under the “divide” strategy).  
Please confirm this does not make replies appear “too instantaneous” and bot-like, especially for long outputs.

---

`24-35`: **`as const` annotation is spot-on – nice type-safety improvement**

Explicit literal roles eliminate accidental widening to `string`, which helps downstream discriminated unions.

</details>
<details>
<summary>src/lib/ai/tools/discord.ts (2)</summary>

`55-60`: **Good move: tighten `sharedState` to `unknown`**

Using `unknown` forces explicit type-narrowing inside sandboxed code and reduces accidental leakage of unsafe `any`. 👍

---

`1-10`: ```shell
#!/bin/bash
# Inspect package.json for 'ai' and 'zod' dependencies
echo "=== dependencies in package.json ==="
grep -R "\"dependencies\"" -n package.json -A 20 || true
echo
echo "=== devDependencies in package.json ==="
grep -R "\"devDependencies\"" -n package.json -A 20 || true
echo
echo "=== Look for 'ai' and 'zod' in package.json ==="
grep -R "\"ai\"" -n package.json || true
grep -R "\"zod\"" -n package.json || true
echo
# Check TS config for path mappings and baseUrl
echo "=== tsconfig.json paths and baseUrl ==="
grep -R "\"paths\"" -n tsconfig.json -A 10 || true
grep -R "\"baseUrl\"" -n tsconfig.json -A 5 || true
src/env.ts (1)

26-35: z.url() is cleaner, but check CI for any string-only uses

Migrating UPSTASH_REDIS_REST_URL to z.url() will now reject non-URL strings (e.g., localhost:6379). Ensure all deployment environments provide a fully qualified URL.

Addition of mandatory EXA_API_KEY is fine, but remember to:

  1. Update secret stores (GitHub Actions, Render, etc.).
  2. Bump .env.example accordingly.
src/utils/status.ts (1)

38-38: Export order change is fine

Re-ordering the named exports has no behavioural impact and matches the call-site order elsewhere in the repo.

src/utils/messages.ts (1)

67-69: Type-guard looks good

instanceof Message && typeof msg.reply === 'function' is sufficient and safe.

src/utils/context.ts (1)

1-4: Import re-ordering only – no concerns

Moving frequently-used imports to the top improves readability and has no functional impact.

src/lib/ai/providers.ts (1)

22-25: Model identifiers may be invalid (o4-mini vs gpt-4o-mini)

OpenAI’s official model names use the gpt-4o prefix. A typo here will surface at runtime with a 404/400 error from the provider.

-    'chat-model': openai.responses('gpt-4.1-mini'),
-    'reasoning-model': openai.responses('o4-mini'),
-    'artifact-model': openai.responses('gpt-4.1'),
-    'relevance-model': openai.responses('gpt-4.1-nano'),
+    // double-check actual model slugs with the provider before merge
+    'chat-model': openai.responses('gpt-4o-mini'),
+    'reasoning-model': openai.responses('gpt-4o-mini'),
+    'artifact-model': openai.responses('gpt-4o'),
+    'relevance-model': openai.responses('gpt-4o-nano'),

Please verify against the latest OpenAI docs or provider helper.

src/lib/ai/tools/search-web.ts (1)

1-4: Verify import paths to avoid bundler/runtime resolution issues

ai and zod/v4 are reported as unresolved by ESLint.
ai – make sure the package is installed and correctly aliased in your build config.
zod/v4 – the canonical import is usually just zod; the sub-path may break on some bundlers (e.g. ts-node, jest).

Confirm these paths resolve in all target environments.

src/commands/voice-channel/leave.ts (1)

4-7: Commenting out the data object disables slash-command registration

With these lines commented, the command loader will skip leave, meaning users cannot invoke it via /leave. If that’s intentional, consider removing the file or adding a deprecated notice; otherwise, restore the builder.

src/utils/sandbox.ts (1)

18-19: Type-safety & error-handling improvements look good

Changing anyunknown, refining the error extraction, and keeping AsyncFunction creation lint-clean are all solid upgrades.

Also applies to: 32-34, 44-48

src/events/message-create/utils/respond.ts (1)

9-11: ESLint “import-x/no-unresolved” warning likely indicates a path-mapping gap

@mem0/vercel-ai-provider is present in package.json but the ESLint resolver can’t locate it, producing noise on every lint.
Either:

  1. add it to typescript.tsconfig.paths / moduleResolution, or
  2. in .eslintrc.json configure settings.import/resolver with node, or
  3. pin an explicit exports field in the lib (if it’s your package fork).

Without fixing this, bun lint (which is run with --max-warnings 0) will always fail CI.

@@ -0,0 +1 @@
export default { extends: ['@commitlint/config-conventional'] };
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

TypeScript config is not loaded by commitlint out-of-the-box

@commitlint/cli expects a plain JS/JSON/YAML config. With the current .ts file, commitlint invoked from the Husky hook will fail to parse the file unless you preload ts-node or run bun commitlint (which transpiles TS).

Two quick fixes:

-// commitlint.config.ts
-export default { extends: ['@commitlint/config-conventional'] };
+// commitlint.config.cjs
+module.exports = { extends: ['@commitlint/config-conventional'] };

or keep the TS file but add:

npm i -D ts-node
echo 'require("ts-node").register();' > commitlint.ts-node.js
# and invoke: commitlint --config commitlint.ts-node.js
🤖 Prompt for AI Agents
In commitlint.config.ts at line 1, the TypeScript config file is not supported
by commitlint CLI by default, causing parsing failures in Husky hooks. To fix
this, either rename the config file to a supported format like
commitlint.config.js with equivalent JS syntax, or keep the TS file but install
ts-node as a dev dependency and create a JS loader file that requires
ts-node/register, then update the commitlint command to use this loader file as
the config.

Comment on lines 51 to 60
DEEPGRAM_API_KEY=your_deepgram_api_key_here
ELEVENLABS_API_KEY=your_elevenlabs_api_key_here
ELEVENLABS_API_KEY=your_elevenlabs_api_key_here

# ---------------------------------------------------------------------------------------------------------
# Search
# Search the web using ExaAI.
# @see https://exa.ai/
# ---------------------------------------------------------------------------------------------------------
EXA_API_KEY=your_exa_api_key_here
Copy link

Choose a reason for hiding this comment

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

🧹 Nitpick (assertive)

🧩 Verification correct

Minor hygiene: add trailing newline and verify var names

• dotenv-linter flags the missing newline at EOF – add one for POSIX compliance.
• Ensure the new keys (ELEVENLABS_API_KEY, EXA_API_KEY) exactly match the identifiers used in src/env.ts; a typo will surface only at runtime.

-EXA_API_KEY=your_exa_api_key_here
+EXA_API_KEY=your_exa_api_key_here
+

🏁 Script executed:

#!/bin/bash
# Verify that env keys exist in codebase
rg -n $'ELEVENLABS_API_KEY|EXA_API_KEY' | head

Length of output: 223


Minor hygiene: add trailing newline and verify var names

• dotenv-linter flags the missing newline at EOF – add one for POSIX compliance.
• Ensure the new keys (ELEVENLABS_API_KEY, EXA_API_KEY) exactly match the identifiers used in src/env.ts; a typo will surface only at runtime.

-EXA_API_KEY=your_exa_api_key_here
+EXA_API_KEY=your_exa_api_key_here
+
#!/bin/bash
# Verify that env keys exist in codebase
rg -n $'ELEVENLABS_API_KEY|EXA_API_KEY' | head
🧰 Tools
🪛 dotenv-linter (3.3.0)

[warning] 60-60: [EndingBlankLine] No blank line at the end of the file

🤖 Prompt for AI Agents
In the .env.example file around lines 52 to 60, add a trailing newline at the
end of the file to comply with POSIX standards. Also, verify that the
environment variable names ELEVENLABS_API_KEY and EXA_API_KEY exactly match
those used in src/env.ts to prevent runtime errors due to typos. Use a search
tool like ripgrep to confirm these keys are correctly referenced in the
codebase.

@@ -0,0 +1 @@
bun lint-staged
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Hard dependency on Bun may break contributor workflow

Not every machine running the repo will have bun installed, causing the pre-commit hook to fail. Consider falling back to npm/pnpm or making the command configurable:

-bun lint-staged
+command -v bun >/dev/null 2>&1 && bun lint-staged || npx lint-staged
📝 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
bun lint-staged
# .husky/pre-commit
command -v bun >/dev/null 2>&1 && bun lint-staged || npx lint-staged
🤖 Prompt for AI Agents
In the .husky/pre-commit file at line 1, the pre-commit hook currently runs the
command "bun lint-staged", which assumes Bun is installed on every contributor's
machine. To fix this, modify the script to check if Bun is available and fall
back to npm or pnpm if not, or make the command configurable via an environment
variable or config file. This ensures the pre-commit hook works regardless of
the package manager installed.

Comment on lines +3 to 5
AudioPlayerStatus,
createAudioResource,
entersState,
Copy link

Choose a reason for hiding this comment

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

🧹 Nitpick (assertive)

Comment references a removed import – clean up for clarity

StreamType was removed from the import list, yet the block comment below (lines 14-17) still talks about StreamType.Arbitrary.
Prune or update that comment to prevent confusion for maintainers.

🤖 Prompt for AI Agents
In src/utils/voice/helpers/audio.ts around lines 3 to 5, the import of
StreamType was removed but the block comment on lines 14 to 17 still references
StreamType.Arbitrary. Update or remove that part of the comment to reflect the
current imports and avoid confusion for future maintainers.

@@ -0,0 +1 @@
* @techwithanirudh No newline at end of file
Copy link

Choose a reason for hiding this comment

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

🧹 Nitpick (assertive)

Add a trailing newline for POSIX-compliance

Most linters/readers expect text files to end with a \n.
Appending one avoids diff noise the next time the file is edited.

-* @techwithanirudh
+* @techwithanirudh
+
📝 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
* @techwithanirudh
* @techwithanirudh
🤖 Prompt for AI Agents
In .github/CODEOWNERS at line 1, the file lacks a trailing newline character
which is required for POSIX-compliance. Add a newline character at the end of
the file to ensure it ends with a '\n', preventing unnecessary diff noise in
future edits.

Comment on lines +82 to +86
"*.{cjs,mjs,js,jsx,cts,mts,ts,tsx,json}": "eslint --fix .",
"**/*": [
"prettier --write --ignore-unknown",
"bun check:spelling"
]
Copy link

Choose a reason for hiding this comment

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

🧹 Nitpick (assertive)

Heavy eslint fix on entire repo per staged commit

"eslint --fix ." runs over the whole codebase for every staged commit, which can take seconds and rewrites unrelated files.
Consider:

"*.{js,ts,tsx}": "eslint --fix"

so eslint only processes the staged subset.

🤖 Prompt for AI Agents
In package.json lines 82 to 86, the current lint-staged configuration runs
"eslint --fix ." on the entire codebase for every staged commit, causing slow
performance and rewriting unrelated files. Modify the eslint command to only run
on the staged files by changing the pattern to "*. {js,ts,tsx}" and removing the
"." argument, so eslint only processes the staged subset of files.

Comment on lines +23 to 26
"check": "bun lint && bun typecheck && bun format:check && bun check:spelling",
"check:spelling": "cspell -c .cspell.json --no-progress --no-summary --no-must-find-files --unique",
"prepare": "husky"
},
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

check and lint-staged commands call scripts incorrectly

bun lint / bun check:spelling execute a file called lint (or check:spelling) instead of an npm-style script.
Use bun run (or plain npm run) so the declared scripts are invoked:

-    "check": "bun lint && bun typecheck && bun format:check && bun check:spelling",
+    "check": "bun run lint && bun run typecheck && bun run format:check && bun run check:spelling",

The same applies inside the lint-staged array:

-      "bun check:spelling"
+      "bun run check:spelling"

Otherwise pre-commit hooks will fail with “ENOENT: no such file or directory ‘lint’”.

📝 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
"check": "bun lint && bun typecheck && bun format:check && bun check:spelling",
"check:spelling": "cspell -c .cspell.json --no-progress --no-summary --no-must-find-files --unique",
"prepare": "husky"
},
// package.json
{
"scripts": {
// …
- "check": "bun lint && bun typecheck && bun format:check && bun check:spelling",
+ "check": "bun run lint && bun run typecheck && bun run format:check && bun run check:spelling",
"check:spelling": "cspell -c .cspell.json --no-progress --no-summary --no-must-find-files --unique",
"prepare": "husky"
},
// …
"lint-staged": [
// other entries
- "bun check:spelling"
+ "bun run check:spelling"
// other entries
]
}
🤖 Prompt for AI Agents
In package.json lines 23 to 26, the scripts "check" and "check:spelling" are
called directly with "bun lint" and "bun check:spelling", which tries to execute
files named "lint" or "check:spelling" instead of running the npm scripts. To
fix this, prefix these commands with "bun run" so they correctly invoke the
npm-style scripts, e.g., use "bun run lint" and "bun run check:spelling". Also,
update any references to these scripts in the lint-staged configuration to use
"bun run" similarly to avoid ENOENT errors during pre-commit hooks.

Comment on lines +9 to +11
Separate Deepgram code into it's files
Implement Conversation history for Voice Chat, previous message memory + chat history.
Add Commit Lint to enforce strict commit messages, and add lint pipelines.
Copy link

Choose a reason for hiding this comment

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

🧹 Nitpick (assertive)

Minor grammar: use possessive “its”

“Separate Deepgram code into it's files”

Should be “its”.

-Separate Deepgram code into it's files
+Separate Deepgram code into its files
📝 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
Separate Deepgram code into it's files
Implement Conversation history for Voice Chat, previous message memory + chat history.
Add Commit Lint to enforce strict commit messages, and add lint pipelines.
Separate Deepgram code into its files
Implement Conversation history for Voice Chat, previous message memory + chat history.
Add Commit Lint to enforce strict commit messages, and add lint pipelines.
🧰 Tools
🪛 LanguageTool

[uncategorized] ~9-~9: Did you mean “its” (the possessive pronoun)?
Context: ...realistic. Separate Deepgram code into it's files Implement Conversation history fo...

(ITS_PREMIUM)

🤖 Prompt for AI Agents
In TODO.md around lines 9 to 11, the phrase "Separate Deepgram code into it's
files" uses the incorrect possessive form "it's." Replace "it's" with the
correct possessive pronoun "its" to fix the grammar.

Implement Conversation history for Voice Chat, previous message memory + chat history.
Add Commit Lint to enforce strict commit messages, and add lint pipelines.
Allow People to Customize Zenix's Speed, and other settings in a /config command (per-server).
Refactor the channels command to be more easy to use, with deny and allow lists.
Copy link

Choose a reason for hiding this comment

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

🧹 Nitpick (assertive)

Wording nit: “more easy” → “easier”

-Refactor the channels command to be more easy to use
+Refactor the channels command to be easier to use
📝 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
Refactor the channels command to be more easy to use, with deny and allow lists.
- Refactor the channels command to be more easy to use, with deny and allow lists.
+ Refactor the channels command to be easier to use, with deny and allow lists.
🧰 Tools
🪛 LanguageTool

[style] ~13-~13: The phrasing ‘more easy’ can sound awkward and informal. Consider using a comparative adjective or other alternative.
Context: ...r). Refactor the channels command to be more easy to use, with deny and allow lists. Det...

(MORE_EASY_N_CLEAR)

🤖 Prompt for AI Agents
In TODO.md at line 13, change the phrase "more easy" to the grammatically
correct "easier" to improve wording clarity.

Comment on lines +76 to 84
3. \`searchWeb\`
- Use this to search the web for information.
- You can search for any topic, and it will return relevant results.
4. \`getWeather\`
- Use this to get the current weather for a specific location.
- You can specify a city or country, and it will return the current weather conditions.
Use the tools responsibly. Plan ahead. With the \`discord\` tool, **make every call count**.
Copy link

Choose a reason for hiding this comment

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

🧹 Nitpick (assertive)

Tool order / numbering drift

The prompt now lists searchWeb as item 3 and getWeather as 4 even though getWeather existed first.
Renumber (or switch to unordered bullets) to avoid confusing the LLM’s “you have X tools” mental model.

🤖 Prompt for AI Agents
In src/lib/ai/prompts.ts between lines 76 and 84, the numbered list of tools is
out of order, listing searchWeb as item 3 and getWeather as item 4, even though
getWeather was introduced first. To fix this, renumber the list so that
getWeather appears before searchWeb, or change the list to use unordered bullets
to prevent confusion in the LLM's understanding of tool order.

@techwithanirudh techwithanirudh merged commit b198b6f into main Jun 18, 2025
1 check passed
@coderabbitai coderabbitai bot mentioned this pull request Jun 24, 2025
8 tasks
This was referenced Jul 27, 2025
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