Skip to content

Conversation

@riatzukiza
Copy link
Owner

@riatzukiza riatzukiza commented Oct 30, 2025

Summary

  • Add ESLint configuration files for improved linting
  • Update TypeScript configurations across packages
  • Add parsers configuration for opencode
  • Update gitignore and pre-push hooks
  • Add lint-errors.js for error tracking

This commit modernizes the project's build and linting infrastructure to improve code quality and developer experience.

Summary by CodeRabbit

  • New Features

    • Added plugin and MCP integrations (weather + remote context) and parser configuration for syntax highlighting across many languages.
  • Chores

    • Introduced and expanded ESLint and TypeScript configurations for stricter checks.
    • Updated package scripts and tooling dependencies; added lint script.
    • Enabled Bun preload and adjusted pre-push hook to run type checks.
  • Cleanup

    • Gitignore and minor formatting/whitespace updates.

@coderabbitai
Copy link

coderabbitai bot commented Oct 30, 2025

Note

Other AI code review bot(s) detected

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

Walkthrough

Adds comprehensive linting and TypeScript tooling, updates Bun and package manifests, introduces Tree-sitter parser configuration and MCP/plugin entries, tweaks husky pre-push to call Bun typecheck, and adds example lint-errors and minor package.json/tsconfig edits.

Changes

Cohort / File(s) Summary
Root repo config
/.gitignore, /.husky/pre-push, /opencode.json, /package.json
Updated gitignore; changed husky pre-push to invoke bun typecheck directly; added plugin and mcp entries (local weather and remote context7) to opencode.json; updated root package.json scripts, description and added c8 and ulid entries.
ESLint & lint examples
/eslint.config.mjs, /lint-errors.js, packages/opencode/eslint.config.js
Added comprehensive root ESLint config (eslint.config.mjs) with TypeScript, FP, import, complexity and test overrides; package-level ESLint config in packages/opencode; added lint-errors.js demonstrating intentional lint violations.
TypeScript configs
/tsconfig.json, packages/sdk/js/tsconfig.json
Replaced/expanded root tsconfig with strict compilerOptions, path mappings and modern targets; added exclude: ["src/gen"] in package tsconfig.
Bun / runtime preload & parsers
packages/opencode/bunfig.toml, packages/opencode/parsers-config.json
Added Bun preload entries and test preload; added Tree-sitter parsers config JSON listing wasm URLs and queries for many languages.
Packages: manifests & dependency changes
packages/opencode/package.json, packages/console/app/package.json, packages/console/core/package.json, packages/plugin/package.json, packages/sdk/js/package.json
Numerous dependency and devDependency additions/changes (ESLint tooling, OpenTUI, Solid, tree-sitter, ulid catalog refactor, tooling like babel/types), new scripts (lint, random), and minor EOF/whitespace edits in some package.json files.
Code & imports
packages/desktop/src/context/sync.tsx, packages/function/src/api.ts
Small public type import addition (Command) and non-functional reflow/whitespace changes to argument formatting.

Sequence Diagram(s)

sequenceDiagram
  participant Dev as Developer (git)
  participant Husky as Husky pre-push
  participant Bun as Bun CLI

  Dev->>Husky: git push triggers pre-push
  Husky->>Bun: run `bun typecheck`
  Bun-->>Husky: typecheck result (success/fail)
  Husky-->>Dev: allow or block push
  Note right of Bun #DDEEFF: Hook now calls `bun typecheck` directly
Loading
sequenceDiagram
  participant App as Opencode runtime
  participant MCP_Local as Local MCP (weather)
  participant MCP_Remote as Remote MCP (context7)

  App->>MCP_Local: spawn `bun x @h1deya/mcp-server-weather` (local)
  MCP_Local-->>App: respond to MCP requests

  App->>MCP_Remote: HTTP POST to https://mcp.context7.com/mcp
  Note right of MCP_Remote #DDEEFF: Includes header CONTEXT7_API_KEY from env
  MCP_Remote-->>App: respond to MCP requests
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

  • Areas to focus review:
    • eslint.config.mjs and packages/opencode/eslint.config.js — many strict and functional rules that could impact large code areas.
    • tsconfig.json — strict compiler options and path mappings may break builds across packages.
    • packages/opencode/parsers-config.json — verify wasm/query URLs and intended languages.
    • opencode.json MCP entries — validate remote URL and environment variable templating.
    • Multiple package.json dependency additions and catalog references — ensure workspace resolution and compatibility.

Poem

🐇
I hopped through configs, lint in paw,
Parsers lined up, strict rules I saw,
Bun checks the push, MCPs reply,
Types stand tall and linters spy,
A rabbit cheers — the repo’s spry! ✨

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 33.33% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title Check ✅ Passed The pull request title "feat: update project configuration and build setup" is directly related to the changeset, which contains extensive configuration and build infrastructure updates including new ESLint configurations, TypeScript configuration updates across multiple packages, package.json modifications, .gitignore updates, pre-push hook modifications, and new parsers configuration. The title accurately conveys that this PR is about modernizing and updating the project's configuration and build systems. While the title is somewhat broad and doesn't highlight specific additions like ESLint configuration, it still clearly summarizes the nature of the changes as configuration and build-related updates, which aligns with the PR objectives stated in the description.
✨ 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 hacks/staging

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.

Copy link

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +1 to +7
import tseslint from '@typescript-eslint/eslint-plugin';
import tsParser from '@typescript-eslint/parser';
import functional from 'eslint-plugin-functional';
import importPlugin from 'eslint-plugin-import';
import promise from 'eslint-plugin-promise';
import sonarjs from 'eslint-plugin-sonarjs';
import ava from 'eslint-plugin-ava';

Choose a reason for hiding this comment

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

P1 Badge Declare required ESLint plugins

The new ESLint config imports eslint-plugin-functional, eslint-plugin-import, eslint-plugin-promise, eslint-plugin-sonarjs, and eslint-plugin-ava, but none of these packages are listed in any workspace package.json. Running ESLint will fail with “Cannot find module …” before any linting occurs. Add these plugins (and ESLint itself if needed) to the repo’s devDependencies so the configuration can load.

Useful? React with 👍 / 👎.

Comment on lines +1 to +13
import type {
Message,
Agent,
Provider,
Session,
Part,
Config,
Path,
File,
FileNode,
Project,
Command,
} from "@opencode-ai/sdk"

Choose a reason for hiding this comment

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

P1 Badge Remove unused Command import

This file adds Command to the @opencode-ai/sdk import list but never uses the type anywhere in the module. Because the updated root tsconfig.json enables noUnusedLocals, the unused import now makes bun typecheck/tsc fail. Drop the import or reference the type to keep the new strict compilation settings passing.

Useful? React with 👍 / 👎.

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

Caution

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

⚠️ Outside diff range comments (2)
packages/desktop/src/context/sync.tsx (2)

115-130: Inconsistent null handling across load functions.

Most load functions use non-null assertions (x.data!) while line 119 uses nullish coalescing (x.data ?? []). If the API can return null data, the non-null assertions will throw runtime errors. Consider standardizing the null handling approach across all load functions.

Apply this diff to add consistent null safety:

 const load = {
-  project: () => sdk.client.project.current().then((x) => setStore("project", x.data!)),
-  provider: () => sdk.client.config.providers().then((x) => setStore("provider", x.data!.providers)),
-  path: () => sdk.client.path.get().then((x) => setStore("path", x.data!)),
+  project: () => sdk.client.project.current().then((x) => x.data && setStore("project", x.data)),
+  provider: () => sdk.client.config.providers().then((x) => x.data && setStore("provider", x.data.providers)),
+  path: () => sdk.client.path.get().then((x) => x.data && setStore("path", x.data)),
   agent: () => sdk.client.app.agents().then((x) => setStore("agent", x.data ?? [])),
   session: () =>
     sdk.client.session.list().then((x) =>
       setStore(
         "session",
         (x.data ?? []).slice().sort((a, b) => a.id.localeCompare(b.id)),
       ),
     ),
-  config: () => sdk.client.config.get().then((x) => setStore("config", x.data!)),
-  changes: () => sdk.client.file.status().then((x) => setStore("changes", x.data!)),
-  node: () => sdk.client.file.list({ query: { path: "/" } }).then((x) => setStore("node", x.data!)),
+  config: () => sdk.client.config.get().then((x) => x.data && setStore("config", x.data)),
+  changes: () => sdk.client.file.status().then((x) => x.data && setStore("changes", x.data)),
+  node: () => sdk.client.file.list({ query: { path: "/" } }).then((x) => x.data && setStore("node", x.data)),
 }

167-195: Untracked setTimeout can cause memory leaks and race conditions.

The setTimeout at line 175 will continue executing even if the component unmounts or another sync is initiated. This can lead to:

  • Memory leaks if the context is destroyed while the timeout is pending
  • Errors when accessing this.sync or setStore after unmount
  • Race conditions if multiple syncs overlap

Consider one of these approaches:

Option 1: Store timeout ID and provide cleanup

+    let retryTimeout: ReturnType<typeof setTimeout> | undefined
+
     return {
       data: store,
       set: setStore,
       get ready() {
         return store.ready
       },
       session: {
         get(sessionID: string) {
           const match = Binary.search(store.session, sessionID, (s) => s.id)
           if (match.found) return store.session[match.index]
           return undefined
         },
         async sync(sessionID: string, isRetry = false) {
+          // Clear any pending retry
+          if (retryTimeout) {
+            clearTimeout(retryTimeout)
+            retryTimeout = undefined
+          }
+
           const [session, messages] = await Promise.all([
             sdk.client.session.get({ path: { id: sessionID } }),
             sdk.client.session.messages({ path: { id: sessionID } }),
           ])

           // If no messages and this might be a new session, retry after a delay
           if (!isRetry && messages.data!.length === 0) {
-            setTimeout(() => this.sync(sessionID, true), 500)
+            retryTimeout = setTimeout(() => {
+              retryTimeout = undefined
+              this.sync(sessionID, true)
+            }, 500)
             return
           }

           setStore(
             produce((draft) => {
               const match = Binary.search(draft.session, sessionID, (s) => s.id)
               draft.session[match.index] = session.data!
               draft.message[sessionID] = messages
                 .data!.map((x) => x.info)
                 .slice()
                 .sort((a, b) => a.id.localeCompare(b.id))
               for (const message of messages.data!) {
                 draft.part[message.info.id] = message.parts
                   .slice()
                   .map(sanitizePart)
                   .sort((a, b) => a.id.localeCompare(b.id))
               }
             }),
           )
         },
       },
       load,
       absolute,
       sanitize,
+      cleanup() {
+        if (retryTimeout) {
+          clearTimeout(retryTimeout)
+        }
+      },
     }

Option 2: Use await with a delay promise (simpler)

           // If no messages and this might be a new session, retry after a delay
           if (!isRetry && messages.data!.length === 0) {
-            setTimeout(() => this.sync(sessionID, true), 500)
-            return
+            await new Promise(resolve => setTimeout(resolve, 500))
+            return this.sync(sessionID, true)
           }
🧹 Nitpick comments (6)
packages/desktop/src/context/sync.tsx (2)

137-153: Consider making sanitizePart immutable.

The function directly mutates part.state.metadata[key] and part.state.input[key] (lines 142, 147). While this works, it modifies the input object which could cause unexpected side effects if the Part objects are cached or reused by the SDK.

Consider creating a new object with sanitized values:

 const sanitizePart = (part: Part) => {
   if (part.type === "tool") {
     if (part.state.status === "completed") {
+      const sanitizedMetadata: Record<string, unknown> = {}
       for (const key in part.state.metadata) {
-        if (typeof part.state.metadata[key] === "string") {
-          part.state.metadata[key] = sanitize(part.state.metadata[key] as string)
-        }
+        sanitizedMetadata[key] = typeof part.state.metadata[key] === "string"
+          ? sanitize(part.state.metadata[key] as string)
+          : part.state.metadata[key]
       }
+      const sanitizedInput: Record<string, unknown> = {}
       for (const key in part.state.input) {
-        if (typeof part.state.input[key] === "string") {
-          part.state.input[key] = sanitize(part.state.input[key] as string)
-        }
+        sanitizedInput[key] = typeof part.state.input[key] === "string"
+          ? sanitize(part.state.input[key] as string)
+          : part.state.input[key]
       }
+      return {
+        ...part,
+        state: {
+          ...part.state,
+          metadata: sanitizedMetadata,
+          input: sanitizedInput,
+        },
+      }
     }
   }
   return part
 }

136-136: Consider using a path utility for more robust path joining.

The current implementation handles basic path joining but may not cover all edge cases like multiple consecutive slashes, trailing slashes, or platform-specific separators.

If not already available, consider using a path utility:

+import { join } from 'path' // or use a cross-platform path utility
+
-const absolute = (path: string) => (store.path.directory + "/" + path).replace("//", "/")
+const absolute = (path: string) => join(store.path.directory, path)

Or normalize the result:

-const absolute = (path: string) => (store.path.directory + "/" + path).replace("//", "/")
+const absolute = (path: string) => (store.path.directory + "/" + path).replace(/\/+/g, "/")
packages/opencode/eslint.config.js (1)

22-22: Reconsider no-console: "error" for a CLI/development tool.

OpenCode is described as an "AI-powered development tool" which likely requires console output for user feedback, logging, and debugging. Setting no-console to "error" may be too restrictive.

Consider one of these alternatives:

Option 1: Downgrade to warning

-      "no-console": "error",
+      "no-console": "warn",

Option 2: Allow specific console methods

-      "no-console": "error",
+      "no-console": ["error", { "allow": ["warn", "error", "info"] }],

Option 3: Disable for CLI tool

-      "no-console": "error",
+      "no-console": "off",
package.json (1)

12-12: Remove or clarify the purpose of the "random" script.

This script appears to serve no functional purpose and looks like leftover debug/test code.

If this script is not needed, remove it:

    "typecheck": "bun turbo typecheck",
    "prepare": "husky",
-    "random": "echo 'Random script'"

If it serves a specific purpose, please clarify or rename it accordingly.

packages/opencode/parsers-config.json (1)

8-12: Consider version pinning for query files to avoid breaking changes.

The query files reference the master branch of nvim-treesitter, which could introduce unexpected breaking changes if that repository updates its queries or renames the branch.

Consider one of these approaches:

Option 1: Pin to specific commit SHA

  "highlights": [
-   "https://raw.githubusercontent.com/nvim-treesitter/nvim-treesitter/refs/heads/master/queries/python/highlights.scm"
+   "https://raw.githubusercontent.com/nvim-treesitter/nvim-treesitter/COMMIT_SHA/queries/python/highlights.scm"
  ],

Option 2: Vendor the query files
Store copies of the query files in your repository under a queries/ directory to ensure stability and allow offline development.

Option 3: Add version tags if available
Check if nvim-treesitter provides tagged releases and use those instead of master.

This pattern applies to all query URLs throughout the file (lines 8-12, 20-24, 32-36, 44-48, 56-60, 68-72, 80-84, 92-92, 101-105, 113-117, 125-129, 137-137, 146-146, 155-155, 164-164, 173-173, 182-182, 191-191, 200-200).

packages/opencode/package.json (1)

13-13: Remove or clarify the purpose of the "random" script.

Similar to the root package.json, this script appears to serve no functional purpose.

If not needed, remove it:

    "dev": "bun run --conditions=browser ./src/index.ts",
-    "random": "echo 'Random script updated at $(date)'"

If it serves a testing or development purpose, consider renaming it to something more descriptive.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between a3ba740 and 596a102.

⛔ Files ignored due to path filters (1)
  • bun.lock is excluded by !**/*.lock
📒 Files selected for processing (18)
  • .gitignore (1 hunks)
  • .husky/pre-push (1 hunks)
  • eslint.config.mjs (1 hunks)
  • lint-errors.js (1 hunks)
  • opencode.json (1 hunks)
  • package.json (3 hunks)
  • packages/console/app/package.json (1 hunks)
  • packages/console/core/package.json (1 hunks)
  • packages/desktop/src/context/sync.tsx (1 hunks)
  • packages/function/src/api.ts (2 hunks)
  • packages/opencode/bunfig.toml (1 hunks)
  • packages/opencode/eslint.config.js (1 hunks)
  • packages/opencode/package.json (4 hunks)
  • packages/opencode/parsers-config.json (1 hunks)
  • packages/plugin/package.json (1 hunks)
  • packages/sdk/js/package.json (1 hunks)
  • packages/sdk/js/tsconfig.json (1 hunks)
  • tsconfig.json (1 hunks)
🧰 Additional context used
🪛 Biome (2.1.2)
packages/opencode/package.json

[error] 27-27: The key @opencode-ai/script was already declared.

This where a duplicated key was declared again.

If a key is defined multiple times, only the last definition takes effect. Previous definitions are ignored.

(lint/suspicious/noDuplicateObjectKeys)

🪛 GitHub Actions: format
packages/opencode/package.json

[warning] 46-46: Duplicate key "@opencode-ai/script" in object literal

package.json

[warning] 46-46: Duplicate key "@opencode-ai/script" in object literal

🪛 GitHub Actions: test
packages/console/app/package.json

[warning] 46-46: Duplicate key "@opencode-ai/script" in object literal.

packages/sdk/js/package.json

[warning] 46-46: Duplicate key "@opencode-ai/script" in object literal.

packages/plugin/package.json

[warning] 46-46: Duplicate key "@opencode-ai/script" in object literal.

packages/opencode/package.json

[warning] 46-46: Duplicate key "@opencode-ai/script" in object literal.

package.json

[warning] 46-46: Duplicate key "@opencode-ai/script" in object literal.

packages/console/core/package.json

[warning] 46-46: Duplicate key "@opencode-ai/script" in object literal.

🪛 GitHub Actions: typecheck
packages/console/app/package.json

[warning] 46-46: Duplicate key "@opencode-ai/script" in object literal.

packages/sdk/js/package.json

[warning] 46-46: Duplicate key "@opencode-ai/script" in object literal.

packages/plugin/package.json

[warning] 46-46: Duplicate key "@opencode-ai/script" in object literal.

packages/opencode/package.json

[warning] 46-46: Duplicate key "@opencode-ai/script" in object literal.

package.json

[warning] 46-46: Duplicate key "@opencode-ai/script" in object literal.

packages/console/core/package.json

[warning] 46-46: Duplicate key "@opencode-ai/script" in object literal.

🔇 Additional comments (14)
packages/function/src/api.ts (1)

241-244: Formatting changes align with linting objectives.

The multi-line reformatting of method calls (getRepoInstallation and installationAuth) across these segments is purely whitespace and aligns with the PR's ESLint configuration updates. No functional changes are introduced.

Also applies to: 247-250, 283-286, 289-292

packages/desktop/src/context/sync.tsx (1)

1-19: LGTM!

The imports are well-organized and include all necessary types and utilities.

packages/sdk/js/package.json (1)

29-29: LGTM! Formatting improvement.

The addition of a trailing newline follows common file formatting conventions.

packages/plugin/package.json (1)

27-27: LGTM! Formatting improvement.

The addition of a trailing newline follows common file formatting conventions.

packages/sdk/js/tsconfig.json (1)

11-12: LGTM! Proper exclusion of generated code.

Excluding the src/gen directory from TypeScript compilation is a best practice, as generated code often doesn't need type-checking and may have style/linting issues.

.husky/pre-push (1)

2-2: LGTM! Simplified command.

The change from bun run typecheck to bun typecheck is valid, as Bun supports both forms for running package.json scripts. The simplified version is cleaner and functionally equivalent.

packages/opencode/bunfig.toml (1)

1-4: No action required — preload paths are valid.

Verification confirms both preload paths exist and are properly configured:

  • ./test/preload.ts exists in packages/opencode
  • @opentui/solid is available as a dependency (version 0.0.0-20251027-327d7e76)
packages/console/core/package.json (1)

17-17: Catalog configuration is properly defined.

The workspace catalog correctly defines ulid with version 3.0.1, and the dependency reference in packages/console/core/package.json is valid. The migration to catalog-based dependency management is correctly implemented.

packages/console/app/package.json (1)

15-18: Verify intentionality of @jsx-email/render fixed version.

Verification confirms @jsx-email/render is not defined in the workspace catalog and uses a fixed version intentionally. The migrations of @kobalte/core and @openauthjs/openauth to catalog-based management are correct. However, consider whether @jsx-email/render should be added to the catalog for consistency, or if the fixed version approach is intentional (e.g., stability, pin requirements).

lint-errors.js (1)

1-45: Clarify the purpose and ensure proper exclusion from linting.

This file contains intentional linting violations but isn't explicitly excluded in eslint.config.mjs. This could cause CI/CD pipeline failures and generate noise in development workflows.

Please clarify:

  1. Is this file intended for testing/demonstration purposes, or should it be removed?
  2. If keeping it, should it be:
    • Moved to a test fixtures directory (e.g., test/fixtures/ or packages/opencode/test/fixtures/)?
    • Explicitly excluded in the ESLint ignore patterns?

If this is a test fixture, apply this pattern:

// In eslint.config.mjs, add to ignores array:
  ignores: [
    '**/dist/**',
    '**/.cache/**',
    './scripts/**',
    './templates/**',
    './eslint.config.ts',
    '**/pseudo/**',
    'packages/smartgpt-bridge/src/fixtures',
+   '**/fixtures/**',
+   'lint-errors.js',
  ],
opencode.json (1)

1-17: LGTM! Configuration structure is clean and follows best practices.

The plugin and MCP configurations are well-structured:

  • Environment variable usage for API keys is secure
  • Both local and remote MCP server types are properly configured
  • Schema reference provides validation
packages/opencode/package.json (2)

9-12: Linting and dev script updates look good.

The addition of the lint script and the --conditions=browser flag for the dev script are appropriate improvements for the development workflow.


62-92: Dependency additions align well with the PR objectives.

The new dependencies support the infrastructure improvements:

  • OpenTUI and Solid.js for UI components
  • ESLint tooling for linting infrastructure
  • tree-sitter packages for parsing
  • Updated web-tree-sitter to 0.26.0

These additions are consistent with modernizing the build and development tooling.

package.json (1)

59-61: Review comment is incorrect; no duplicate dependency exists.

The verification confirms there is no duplicate key in the dependencies object. The grep search found "@opencode-ai/script" only once at line 59, and the jq analysis of the dependencies object shows all three keys are unique ("@opencode-ai/script", "@opencode-ai/sdk", "c8"). Additionally, line 46 contains "virtua": "0.42.3", not "@opencode-ai/script". The snippet at lines 59–61 is valid as-is.

Likely an incorrect or invalid review comment.

Comment on lines +13 to +16
opencode-lsp-test/
.serena/

.serena/
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

Remove duplicate .serena/ entry.

The .serena/ directory is listed twice (lines 14 and 16). Remove one of the duplicate entries to keep the .gitignore file clean.

Apply this diff to remove the duplicate:

 opencode-lsp-test/
 .serena/
-
-.serena/
📝 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
opencode-lsp-test/
.serena/
.serena/
opencode-lsp-test/
.serena/
🤖 Prompt for AI Agents
In .gitignore around lines 13 to 16, there is a duplicate entry for ".serena/"
(appears on lines 14 and 16); remove the redundant second ".serena/" line so the
directory is only listed once, leaving a single ".serena/" entry and preserving
other entries and spacing.

Comment on lines +44 to +47
'max-lines': ['error', { max: 300, skipBlankLines: true, skipComments: true }],
'max-lines-per-function': ['error', { max: 50, IIFEs: true }],
'max-params': ['error', 4],
complexity: ['error', 15],
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

Verify that complexity and size limits align with existing codebase.

The configuration enforces strict limits:

  • Max 300 lines per file
  • Max 50 lines per function
  • Max 4 parameters
  • Cyclomatic complexity ≤ 15
  • Cognitive complexity ≤ 15

These are quite strict and may require significant refactoring of existing code.

Before enforcing these limits, verify the current state of the codebase:

Consider starting with warnings instead of errors to assess the impact:

-      'max-lines': ['error', { max: 300, skipBlankLines: true, skipComments: true }],
-      'max-lines-per-function': ['error', { max: 50, IIFEs: true }],
+      'max-lines': ['warn', { max: 300, skipBlankLines: true, skipComments: true }],
+      'max-lines-per-function': ['warn', { max: 50, IIFEs: true }],

🏁 Script executed:

#!/bin/bash
# Find large files and functions
echo "Files over 300 lines:"
fd -e ts -e tsx -x wc -l {} \; | awk '$1 > 300 {print $0}' | sort -rn | head -20

echo ""
echo "Sample of functions that might exceed limits:"
# This is a heuristic - proper analysis would need AST parsing
rg -n "^(export )?(async )?function" --type ts -A 60 | grep -E "^[0-9]+-.*function" | head -10

Length of output: 968


I need to gather more information about function lengths, generated files, and whether the eslint config already excludes certain files.


🏁 Script executed:

#!/bin/bash
# Check for .eslintignore or ignorePatterns in eslint config
echo "=== Checking ESLint exclusions ==="
if [ -f .eslintignore ]; then
  echo ".eslintignore exists:"
  cat .eslintignore
else
  echo "No .eslintignore file found"
fi

echo ""
echo "=== Checking eslint.config.mjs for ignorePatterns ==="
grep -n "ignore" ./eslint.config.mjs | head -20

echo ""
echo "=== Generated files check ==="
echo "Generated TypeScript files (.gen.ts):"
fd -e gen.ts | head -10

Length of output: 855


🏁 Script executed:

#!/bin/bash
# Better function length analysis using AST patterns
echo "=== Functions over 50 lines (sample) ==="
# Search for function declarations and count lines until next function or export
ast-grep --pattern $'function $_ ($_) {
  $$$
}' -A 60 | head -100

Length of output: 5471


🏁 Script executed:

#!/bin/bash
# Check eslint.config.mjs structure to understand current configuration
echo "=== Current eslint.config.mjs context ==="
cat ./eslint.config.mjs | head -60

Length of output: 2007


I need to verify whether the .gen.ts files are auto-generated and if they should be excluded from linting.


🏁 Script executed:

#!/bin/bash
# Check if .gen.ts files are auto-generated (look for generation markers)
echo "=== Checking .gen.ts files for generation markers ==="
rg -n "generated|do not edit|auto-generated" packages/sdk/js/src/gen/types.gen.ts -A 2 -B 2 | head -20

echo ""
echo "=== Check build config for code generation ==="
fd -e "package.json" | xargs grep -l "codegen\|generate" | head -5

Length of output: 186


🏁 Script executed:

#!/bin/bash
# Check if non-generated files can realistically fit within limits
echo "=== Largest non-.gen.ts files ==="
fd -e ts -e tsx ! -path "*/.gen.ts" -x wc -l {} \; | awk '$1 > 300 {print $0}' | sort -rn | head -15

Length of output: 202


🏁 Script executed:

#!/bin/bash
echo "=== Largest non-generated files (excluding .gen.ts) ==="
fd -e ts -e tsx -x wc -l {} \; | grep -v "\.gen\.ts" | awk '$1 > 300 {print $0}' | sort -rn | head -15

Length of output: 740


Exclude auto-generated files and consider starting with warnings for linting limits.

The configuration enforces strict limits that will require codebase refactoring:

  • File size: 15+ non-generated files exceed 300 lines (largest: 4,454 lines for web icons)
  • Function size: Functions exceed 50-line limit (e.g., ~60+ lines observed in scripts)
  • Parameters/complexity: Max 4 parameters and complexity ≤ 15

Two critical issues:

  1. Add .gen.ts exclusion: Auto-generated files (e.g., packages/sdk/js/src/gen/*.gen.ts generated by @hey-api/openapi-ts) must be excluded from these rules since they're not handwritten code.

  2. Consider starting with warn instead of error: This allows development to continue while violations are addressed incrementally:

    -      'max-lines': ['error', { max: 300, skipBlankLines: true, skipComments: true }],
    -      'max-lines-per-function': ['error', { max: 50, IIFEs: true }],
    +      'max-lines': ['warn', { max: 300, skipBlankLines: true, skipComments: true }],
    +      'max-lines-per-function': ['warn', { max: 50, IIFEs: true }],

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

🤖 Prompt for AI Agents
In eslint.config.mjs around lines 44 to 47, the current rules ('max-lines',
'max-lines-per-function', 'max-params', 'complexity') are applied as errors and
do not exclude generated files; update the config to exclude auto-generated
files (e.g., add a pattern like packages/sdk/js/src/gen/**/*.gen.ts to the
appropriate ignoreFiles or overrides.excludePatterns) so those .gen.ts files are
not checked, and change the rule severities from 'error' to 'warn' (at least
initially) for the listed rules so violations surface as warnings while the
codebase is remediated.

Comment on lines +67 to +84
'no-restricted-syntax': [
'error',
{
selector: "CallExpression[callee.name='require']",
message: 'ESM only',
},
{
selector: "MemberExpression[object.name='module'][property.name='exports']",
message: 'ESM only',
},
{
selector: 'ClassDeclaration',
message: 'Class declarations are not allowed.',
},
{
selector: 'ClassExpression',
message: 'Class expressions are not allowed.',
},
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

Reconsider the ban on class declarations and expressions.

Lines 78-84 completely prohibit class usage, which is extremely restrictive and may conflict with third-party libraries, framework requirements, or legitimate use cases (e.g., custom errors, builder patterns).

While functional programming has benefits, a complete ban on classes might be too extreme for a real-world project. Consider:

  1. If classes are truly unwanted in your codebase, ensure this aligns with team consensus and existing code patterns
  2. If this rule is too strict, either remove it or allow classes in specific contexts:
-        {
-          selector: 'ClassDeclaration',
-          message: 'Class declarations are not allowed.',
-        },
-        {
-          selector: 'ClassExpression',
-          message: 'Class expressions are not allowed.',
-        },

Check if classes are already used in the codebase:

If classes are found, you'll need to refactor them or adjust this rule.


🏁 Script executed:

#!/bin/bash
# Search for existing class usage
echo "Searching for class declarations in TypeScript files..."
ast-grep --pattern 'class $_ { $$$ }'

Length of output: 4439



🏁 Script executed:

#!/bin/bash
# Check eslint.config.mjs for ignore patterns and file scope
echo "=== Checking eslint.config.mjs for ignores and scope ==="
cat eslint.config.mjs | head -100

Length of output: 3401


🏁 Script executed:

#!/bin/bash
# Search for more class usages to get full picture
echo "=== Searching for all class declarations ==="
rg -n "^\s*(export\s+)?(abstract\s+)?class\s+" --type=ts --type=js -g '!node_modules' -g '!dist' | head -20

Length of output: 1594


🏁 Script executed:

#!/bin/bash
# Check if there are any ESLint ignores or overrides for generated files
echo "=== Checking for ESLint ignores in package.json or other configs ==="
find . -maxdepth 2 -type f \( -name ".eslintignore" -o -name "eslintrc*" -o -name "package.json" \) ! -path '*/node_modules/*' -exec echo "File: {}" \; -exec cat {} \; 2>/dev/null | head -150

Length of output: 2712


The class ban rule will cause linting failures on existing codebase—critical conflict.

The ESLint config applies to all TypeScript files across the repository without ignoring the real source code. However, classes already exist extensively throughout:

  • Real source: packages/opencode/src/util/queue.ts (AsyncQueue), packages/opencode/src/util/error.ts (NamedError), packages/opencode/src/acp/session.ts (ACPSessionManager), packages/opencode/src/acp/agent.ts (Agent), and custom error classes in multiple files
  • Generated code: packages/sdk/js/src/gen/sdk.gen.ts (20+ generated classes)

Enabling this rule will break the linting pipeline. Either:

  1. Remove the ClassDeclaration and ClassExpression selectors from no-restricted-syntax
  2. Add packages/sdk/js/src/gen/** to ignores for generated code
  3. Refactor all existing classes (20+) to remove class usage
🤖 Prompt for AI Agents
In eslint.config.mjs around lines 67-84, the added 'no-restricted-syntax'
selectors banning ClassDeclaration and ClassExpression will cause repo-wide lint
failures because many real and generated files use classes; fix by removing the
ClassDeclaration and ClassExpression selector entries from this rule, and add an
ignore/override for generated code (e.g., add packages/sdk/js/src/gen/** to the
ignorePatterns or create an override that disables this rule for that glob) so
existing classes keep linting clean; alternatively restrict the rule to only
target specific files where classes must be banned rather than applying it
globally.

Comment on lines +121 to +138
'no-restricted-imports': [
'error',
{
paths: [
{
name: '@promethean/persistence',
importNames: ['ContextStore'],
message: 'Use makeContextStore (functional) instead of class ContextStore.',
},
{
name: '@promethean/agents/agent-context',
importNames: ['DefaultContextManager', 'ContextManager'],
message:
'This is agent state, not LLM conversation. Import makeAgentStateManager (or LegacyAgentStateManager alias) instead.',
},
],
},
],
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

Remove or update references to non-existent @promethean packages.

The no-restricted-imports rules reference @promethean/persistence and @promethean/agents/agent-context packages that don't exist in this repository (based on package.json showing @opencode-ai/* packages).

These rules will either fail to load or never trigger. They appear to be copied from another project's configuration.

Verify if these packages exist:

If these packages don't exist, remove these restriction rules:

      'no-restricted-imports': [
        'error',
        {
-          paths: [
-            {
-              name: '@promethean/persistence',
-              importNames: ['ContextStore'],
-              message: 'Use makeContextStore (functional) instead of class ContextStore.',
-            },
-            {
-              name: '@promethean/agents/agent-context',
-              importNames: ['DefaultContextManager', 'ContextManager'],
-              message:
-                'This is agent state, not LLM conversation. Import makeAgentStateManager (or LegacyAgentStateManager alias) instead.',
-            },
-          ],
+          paths: [],
        },
      ],

🏁 Script executed:

#!/bin/bash
# Search for @promethean packages in the codebase
echo "Searching for @promethean package usage..."
rg -n "@promethean/(persistence|agents)" --type ts --type js

echo ""
echo "Available workspace packages:"
cat package.json | jq -r '.workspaces.packages[]'

Length of output: 134



---

🏁 Script executed:

```shell
#!/bin/bash
# Get actual package names and structure
echo "Checking package.json for actual package dependencies:"
cat package.json | jq '.dependencies | keys[] | select(startswith("@")) | .[0:20]' 2>/dev/null | head -20

echo ""
echo "Checking workspace package.json files for context-related packages:"
find packages -name package.json -maxdepth 3 | xargs grep -l "ContextStore\|ContextManager\|persistence\|agent-context" 2>/dev/null || echo "No matches found"

echo ""
echo "Listing actual workspace packages:"
ls -d packages/*/package.json 2>/dev/null | head -10

Length of output: 265


Remove references to non-existent @promethean packages in no-restricted-imports rules.

The restricted import rules reference @promethean/persistence and @promethean/agents/agent-context, which do not exist in this repository. Verification confirms no usage of these packages anywhere in the codebase. These rules will never trigger and appear to be copied from another project's configuration.

Remove these restriction rules from lines 125-133:

      'no-restricted-imports': [
        'error',
        {
          paths: [
-           {
-             name: '@promethean/persistence',
-             importNames: ['ContextStore'],
-             message: 'Use makeContextStore (functional) instead of class ContextStore.',
-           },
-           {
-             name: '@promethean/agents/agent-context',
-             importNames: ['DefaultContextManager', 'ContextManager'],
-             message:
-               'This is agent state, not LLM conversation. Import makeAgentStateManager (or LegacyAgentStateManager alias) instead.',
-           },
          ],
        },
      ],
🤖 Prompt for AI Agents
eslint.config.mjs lines 121-138: remove the two no-restricted-imports entries
that reference non-existent packages (@promethean/persistence with importNames
['ContextStore'] and @promethean/agents/agent-context with importNames
['DefaultContextManager','ContextManager']). Edit the no-restricted-imports rule
to delete those path objects so the rule only contains valid restrictions for
packages present in this repo, and ensure the surrounding array/formatting
remains valid (comma separation and trailing commas) after removal.

Comment on lines +27 to 46
"@opencode-ai/script": "workspace:*",
"@parcel/watcher-darwin-arm64": "2.5.1",
"@parcel/watcher-darwin-x64": "2.5.1",
"@parcel/watcher-linux-arm64-glibc": "2.5.1",
"@parcel/watcher-linux-x64-glibc": "2.5.1",
"@parcel/watcher-win32-x64": "2.5.1",
"@standard-schema/spec": "1.0.0",
"@tsconfig/bun": "catalog:",
"@types/babel__core": "7.20.5",
"@types/bun": "catalog:",
"@types/turndown": "5.0.5",
"@types/yargs": "17.0.33",
"typescript": "catalog:",
"@typescript-eslint/eslint-plugin": "8.46.2",
"@typescript-eslint/parser": "8.46.2",
"@typescript/native-preview": "catalog:",
"typescript": "catalog:",
"vscode-languageserver-types": "3.17.5",
"why-is-node-running": "3.2.2",
"zod-to-json-schema": "3.24.5",
"@opencode-ai/script": "workspace:*"
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

Fix the duplicate @opencode-ai/script dependency.

Static analysis and pipeline failures indicate that @opencode-ai/script appears twice in the devDependencies object (lines 27 and 46). Package managers will only honor one definition, leading to unpredictable behavior.

Remove one of the duplicate entries:

    "@opencode-ai/script": "workspace:*",
    ...
    "zod-to-json-schema": "3.24.5",
-    "@opencode-ai/script": "workspace:*"

The duplicate should be at line 46 based on the pipeline warnings. Keep only the first declaration at line 27.

📝 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
"@opencode-ai/script": "workspace:*",
"@parcel/watcher-darwin-arm64": "2.5.1",
"@parcel/watcher-darwin-x64": "2.5.1",
"@parcel/watcher-linux-arm64-glibc": "2.5.1",
"@parcel/watcher-linux-x64-glibc": "2.5.1",
"@parcel/watcher-win32-x64": "2.5.1",
"@standard-schema/spec": "1.0.0",
"@tsconfig/bun": "catalog:",
"@types/babel__core": "7.20.5",
"@types/bun": "catalog:",
"@types/turndown": "5.0.5",
"@types/yargs": "17.0.33",
"typescript": "catalog:",
"@typescript-eslint/eslint-plugin": "8.46.2",
"@typescript-eslint/parser": "8.46.2",
"@typescript/native-preview": "catalog:",
"typescript": "catalog:",
"vscode-languageserver-types": "3.17.5",
"why-is-node-running": "3.2.2",
"zod-to-json-schema": "3.24.5",
"@opencode-ai/script": "workspace:*"
"@opencode-ai/script": "workspace:*",
"@parcel/watcher-darwin-arm64": "2.5.1",
"@parcel/watcher-darwin-x64": "2.5.1",
"@parcel/watcher-linux-arm64-glibc": "2.5.1",
"@parcel/watcher-linux-x64-glibc": "2.5.1",
"@parcel/watcher-win32-x64": "2.5.1",
"@standard-schema/spec": "1.0.0",
"@tsconfig/bun": "catalog:",
"@types/babel__core": "7.20.5",
"@types/bun": "catalog:",
"@types/turndown": "5.0.5",
"@types/yargs": "17.0.33",
"@typescript-eslint/eslint-plugin": "8.46.2",
"@typescript-eslint/parser": "8.46.2",
"@typescript/native-preview": "catalog:",
"typescript": "catalog:",
"vscode-languageserver-types": "3.17.5",
"why-is-node-running": "3.2.2",
"zod-to-json-schema": "3.24.5"
🧰 Tools
🪛 Biome (2.1.2)

[error] 27-27: The key @opencode-ai/script was already declared.

This where a duplicated key was declared again.

If a key is defined multiple times, only the last definition takes effect. Previous definitions are ignored.

(lint/suspicious/noDuplicateObjectKeys)

🪛 GitHub Actions: format

[warning] 46-46: Duplicate key "@opencode-ai/script" in object literal

🪛 GitHub Actions: test

[warning] 46-46: Duplicate key "@opencode-ai/script" in object literal.

🪛 GitHub Actions: typecheck

[warning] 46-46: Duplicate key "@opencode-ai/script" in object literal.

🤖 Prompt for AI Agents
In packages/opencode/package.json around lines 27 to 46, there is a duplicate
devDependency entry for "@opencode-ai/script" (present at line 27 and again at
line 46); remove the second occurrence at line 46 so only the first declaration
at line 27 remains, preserving valid JSON punctuation (commas) and formatting.

Comment on lines +35 to +39
"paths": {
"@shared/ts/*": ["../shared/ts/dist/*"],
"@promethean/test-utils/*": ["../packages/test-utils/dist/*"],
"@promethean/legacy/*": ["../packages/legacy/*"]
}
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

Fix or remove invalid path mappings.

The path mappings reference @promethean/* and @shared/* packages that don't appear to exist in this repository. Based on the package.json files, this project uses @opencode-ai/* packages instead.

These invalid paths could cause TypeScript compilation errors and IDE navigation issues.

Run the following script to verify if these directories exist:

If these directories don't exist, remove the invalid mappings or update them to match your actual project structure:

    "baseUrl": ".",
-    "paths": {
-      "@shared/ts/*": ["../shared/ts/dist/*"],
-      "@promethean/test-utils/*": ["../packages/test-utils/dist/*"],
-      "@promethean/legacy/*": ["../packages/legacy/*"]
-    }

🏁 Script executed:

#!/bin/bash
# Check if the mapped directories exist
echo "Checking path mappings..."

[ -d "../shared/ts/dist" ] && echo "✓ ../shared/ts/dist exists" || echo "✗ ../shared/ts/dist NOT FOUND"
[ -d "../packages/test-utils/dist" ] && echo "✓ ../packages/test-utils/dist exists" || echo "✗ ../packages/test-utils/dist NOT FOUND"
[ -d "../packages/legacy" ] && echo "✓ ../packages/legacy exists" || echo "✗ ../packages/legacy NOT FOUND"

echo ""
echo "Actual workspace packages:"
fd -t d -d 1 . packages/

Length of output: 352


🏁 Script executed:

#!/bin/bash
# Check if path aliases are actually used in the codebase
echo "=== Searching for imports using @promethean/* and @shared/* ==="
rg -n "from\s+['\"]@(promethean|shared)/" --type=ts --type=tsx --type=js --type=jsx 2>/dev/null | head -20

echo ""
echo "=== Checking tsconfig references in package.json ==="
cat package.json | grep -A5 -B5 "tsconfig" 2>/dev/null || echo "No tsconfig references found"

Length of output: 782


🏁 Script executed:

#!/bin/bash
# Verify if @promethean or @shared packages exist as npm packages/workspaces
echo "=== Checking package.json for workspace/package references ==="
if [ -f "package.json" ]; then
  grep -E '"(@promethean|@shared)' package.json || echo "No @promethean or @shared references in package.json"
fi

echo ""
echo "=== Checking for any package.json files in parent directories ==="
ls -la ../package.json 2>/dev/null || echo "No package.json in parent directory"
ls -la ../packages/*/package.json 2>/dev/null | head -5

Length of output: 218


Remove invalid and unused path mappings from tsconfig.json.

The path mappings for @promethean/* and @shared/* reference non-existent directories and are not imported or used anywhere in the codebase. They should be removed to avoid configuration confusion:

    "paths": {
-      "@shared/ts/*": ["../shared/ts/dist/*"],
-      "@promethean/test-utils/*": ["../packages/test-utils/dist/*"],
-      "@promethean/legacy/*": ["../packages/legacy/*"]
    }
📝 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
"paths": {
"@shared/ts/*": ["../shared/ts/dist/*"],
"@promethean/test-utils/*": ["../packages/test-utils/dist/*"],
"@promethean/legacy/*": ["../packages/legacy/*"]
}
"paths": {
}
🤖 Prompt for AI Agents
In tsconfig.json around lines 35 to 39, remove the invalid/unreferenced path
mappings for "@shared/ts/*", "@promethean/test-utils/*", and
"@promethean/legacy/*" from the "paths" section; ensure only valid, used path
aliases remain, save the file, then run a TypeScript build or IDE project
refresh to verify there are no unresolved path mappings or import errors.

- Add ESLint configuration files for improved linting
- Update TypeScript configurations across packages
- Add parsers configuration for opencode
- Update gitignore and pre-push hooks
- Add lint-errors.js for error tracking
- Update root package.json with new dependencies
- Refresh bun.lock with latest package versions
- Update package.json files across all packages
- Sync dependency versions for consistency
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: 1

♻️ Duplicate comments (4)
.gitignore (1)

13-16: Remove duplicate .serena/ entry.

This issue was previously flagged and remains unaddressed. The .serena/ directory is listed twice (lines 14 and 16). Remove one of the duplicate entries to keep the .gitignore file clean.

Apply this diff to remove the duplicate:

 opencode-lsp-test/
 .serena/
-
-.serena/
eslint.config.mjs (1)

78-84: Class ban breaks current codebase

no-restricted-syntax now errors on every ClassDeclaration/ClassExpression, but we still ship classes (e.g., SyncServer in packages/function/src/api.ts). Running ESLint on the current tree will fail immediately. Please relax this rule (or scope it narrowly) so existing code passes before merging.

Apply this diff (or equivalent) to unblock linting:

       'no-restricted-syntax': [
         'error',
         {
           selector: "CallExpression[callee.name='require']",
           message: 'ESM only',
         },
         {
           selector: "MemberExpression[object.name='module'][property.name='exports']",
           message: 'ESM only',
         },
-        {
-          selector: 'ClassDeclaration',
-          message: 'Class declarations are not allowed.',
-        },
-        {
-          selector: 'ClassExpression',
-          message: 'Class expressions are not allowed.',
-        },
       ],
packages/opencode/package.json (1)

27-27: Fix the duplicate @opencode-ai/script dependency.

The @opencode-ai/script key appears twice in devDependencies (lines 27 and 46). Package managers only honor the last definition, leading to unpredictable behavior.

Remove the duplicate entry at line 46:

    "zod-to-json-schema": "3.24.5",
-    "@opencode-ai/script": "workspace:*"

Also applies to: 46-46

tsconfig.json (1)

35-39: Remove invalid and unused path mappings.

The path mappings for @promethean/* and @shared/* reference non-existent directories and are not used anywhere in the codebase. Remove them to avoid configuration confusion.

    "baseUrl": ".",
-    "paths": {
-      "@shared/ts/*": ["../shared/ts/dist/*"],
-      "@promethean/test-utils/*": ["../packages/test-utils/dist/*"],
-      "@promethean/legacy/*": ["../packages/legacy/*"]
-    }
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 596a102 and 0ed74f1.

⛔ Files ignored due to path filters (1)
  • bun.lock is excluded by !**/*.lock
📒 Files selected for processing (18)
  • .gitignore (1 hunks)
  • .husky/pre-push (1 hunks)
  • eslint.config.mjs (1 hunks)
  • lint-errors.js (1 hunks)
  • opencode.json (1 hunks)
  • package.json (3 hunks)
  • packages/console/app/package.json (1 hunks)
  • packages/console/core/package.json (1 hunks)
  • packages/desktop/src/context/sync.tsx (1 hunks)
  • packages/function/src/api.ts (2 hunks)
  • packages/opencode/bunfig.toml (1 hunks)
  • packages/opencode/eslint.config.js (1 hunks)
  • packages/opencode/package.json (4 hunks)
  • packages/opencode/parsers-config.json (1 hunks)
  • packages/plugin/package.json (1 hunks)
  • packages/sdk/js/package.json (1 hunks)
  • packages/sdk/js/tsconfig.json (1 hunks)
  • tsconfig.json (1 hunks)
✅ Files skipped from review due to trivial changes (2)
  • packages/plugin/package.json
  • packages/sdk/js/package.json
🚧 Files skipped from review as they are similar to previous changes (5)
  • packages/desktop/src/context/sync.tsx
  • packages/console/core/package.json
  • packages/opencode/parsers-config.json
  • opencode.json
  • package.json
🧰 Additional context used
🪛 Biome (2.1.2)
packages/opencode/package.json

[error] 27-27: The key @opencode-ai/script was already declared.

This where a duplicated key was declared again.

If a key is defined multiple times, only the last definition takes effect. Previous definitions are ignored.

(lint/suspicious/noDuplicateObjectKeys)

🪛 GitHub Actions: format
packages/opencode/package.json

[warning] 46-46: Duplicate key "@opencode-ai/script" in object literal.

🪛 GitHub Actions: test
packages/opencode/package.json

[warning] 46-46: Duplicate key '@opencode-ai/script' in object literal.

packages/console/app/package.json

[warning] 46-46: Duplicate key '@opencode-ai/script' in object literal.

🪛 GitHub Actions: typecheck
packages/opencode/package.json

[warning] 46-46: Duplicate key '@opencode-ai/script' in object literal.

packages/console/app/package.json

[warning] 46-46: Duplicate key "@opencode-ai/script" in object literal.

🔇 Additional comments (9)
packages/console/app/package.json (2)

15-15: New dependencies align with PR objectives.

The addition of @opencode-ai/console-mail (workspace dependency) and @jsx-email/render aligns well with the PR's modernization objectives and the new mail integration feature.

Also applies to: 18-18


15-18: ****

The original review comment incorrectly reported a duplicate key error at line 46. Verification confirms:

  • The package.json file is valid JSON with no duplicate keys
  • The file is 34 lines long (not 46)
  • The dependency changes on lines 15-18 are syntactically correct

No action required; the file is in a valid state.

Likely an incorrect or invalid review comment.

.husky/pre-push (1)

2-2: Direct bun typecheck invocation LGTM

Running Bun’s built-in type checker directly keeps the hook simple and equivalent to the prior script run.

packages/opencode/bunfig.toml (1)

1-4: Preload wiring looks good

The shared and test preload entries align Bun with the new Solid-based setup.

packages/function/src/api.ts (2)

241-250: Formatting-only change confirmed

Reflowing the arguments keeps semantics intact.

Also applies to: 247-250


283-292: Second installation fetch formatting looks good

Consistent wrapping; no logic change.

Also applies to: 289-292

lint-errors.js (1)

1-45: Fixture acknowledged

Understood that this file is a deliberate lint playground; make sure it stays out of production bundles.

Please double-check that your build tooling and publish steps ignore lint-errors.js.

packages/sdk/js/tsconfig.json (1)

11-12: LGTM - Excluding generated sources is good practice.

Excluding src/gen prevents TypeScript from compiling generated code, which is a standard practice and improves build performance.

packages/opencode/eslint.config.js (1)

1-29: LGTM - ESLint configuration is well-structured.

The configuration correctly extends the recommended config and applies TypeScript-specific overrides. The rule set appropriately disables the base no-unused-vars in favor of the TypeScript version, and enables common quality rules.

Comment on lines +16 to +17
"@openauthjs/openauth": "catalog:",
"@kobalte/core": "catalog:",
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

Verify catalog entries exist in root package.json.

Lines 16–17 migrate @openauthjs/openauth and @kobalte/core from explicit versions to catalog: references. Ensure these entries are defined in the root package.json catalog field.


🏁 Script executed:

#!/bin/bash
# Description: Verify catalog entries exist in root package.json

# Check if root package.json has a catalog field with the required entries
cat package.json | jq '.catalog | keys | .[]' 2>/dev/null | grep -E "@openauthjs/openauth|@kobalte/core"

# If not found, list available catalog entries
echo "--- Available catalog entries ---"
cat package.json | jq '.catalog | keys' 2>/dev/null || echo "No catalog field found in root package.json"

Length of output: 77


I need to gather more information. The script shows no catalog field exists, but I should verify the project structure and the current state of the packages.

I need to check the correct location. Catalogs are defined in the pnpm-workspace.yaml file, not in package.json. Let me verify the pnpm-workspace.yaml file.

[skip_cloning_removal]

🏁 Script executed:

#!/bin/bash
# Description: Verify catalog entries exist in pnpm-workspace.yaml

# Check if pnpm-workspace.yaml exists and has catalog entries
if [ -f pnpm-workspace.yaml ]; then
  echo "--- pnpm-workspace.yaml found ---"
  cat pnpm-workspace.yaml | grep -A 20 "^catalog:"
  echo ""
  echo "--- Checking for specific packages ---"
  cat pnpm-workspace.yaml | grep -E "@openauthjs/openauth|@kobalte/core"
else
  echo "pnpm-workspace.yaml not found at root"
fi

# Also verify the current state of packages/console/app/package.json
echo ""
echo "--- Current dependencies in packages/console/app/package.json ---"
cat packages/console/app/package.json | jq '.dependencies | to_entries[] | select(.key == "@openauthjs/openauth" or .key == "@kobalte/core")'

Length of output: 215


Create pnpm-workspace.yaml with catalog entries for @openauthjs/openauth and @kobalte/core.

The PR references packages using the catalog: protocol in packages/console/app/package.json (lines 16–17), but verification shows no pnpm-workspace.yaml file exists at the repository root. Catalogs are defined in the pnpm-workspace.yaml file, and without it, the dependencies cannot resolve. Create the file with catalog entries for both packages or revert to explicit versions.

🤖 Prompt for AI Agents
In packages/console/app/package.json (lines 16–17) the dependencies use the pnpm
"catalog:" protocol for @openauthjs/openauth and @kobalte/core but there is no
pnpm-workspace.yaml at the repo root to define those catalogs; create a
pnpm-workspace.yaml at the repository root that declares a catalogs: section
with entries for both packages pointing to the correct local paths (or git
locations) where those packages live (e.g., map @openauthjs/openauth and
@kobalte/core to their workspace folders), or alternatively change the two
dependencies in package.json to explicit version strings instead of using
catalog:. Ensure the pnpm-workspace.yaml is committed to the repo root so pnpm
can resolve the catalog: protocol.

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