Skip to content

Conversation

paviko
Copy link

@paviko paviko commented Oct 16, 2025

Fixes #98

This PR possibly fixes multiple workspaces problem.

Instance state is tied to a single Project. Services like WebViewManager and WecoderPluginService are marked with @service(Service.Level.PROJECT) and store the active WebViewInstance and RPC connection in project-scoped fields (WebViewManager.getLatestWebView(), PluginContext.getRPCProtocol()), but they also relied on static/singleton access (WecoderPlugin.getInstance(project), PluginContext.getInstance(project)). When a second IDE window opens, the new project gets fresh service instances while the extension process was still running for the first project. The new window never registered a WebView because the extension host remained bound to the earlier ExtensionHostManager, so the RunVSAgentToolWindowContent placeholder kept showing, producing e.g. the blank web view.

Summary by CodeRabbit

  • Refactor
    • Refactored internal resource management to operate on a per-project basis instead of using global storage.
    • Removed unused imports from several internal components.
    • Updated resource lifecycle methods to align with per-project resource management.

Copy link

coderabbitai bot commented Oct 16, 2025

Walkthrough

The changes migrate SystemObjectProvider from global lifecycle management to per-project lifecycle management, enabling support for multiple workspaces. Unused imports are removed from three actor files. Method signatures are updated to require Project parameters for registration, retrieval, and disposal operations.

Changes

Cohort / File(s) Summary
Removed unused imports
jetbrains_plugin/src/main/kotlin/com/sina/weibo/agent/actors/MainThreadLanguageModelToolsShape.kt, MainThreadTaskShape.kt, MainThreadWindowShape.kt
Removed import of com.sina.weibo.agent.plugin.SystemObjectProvider from three actor files.
Per-project storage refactor
jetbrains_plugin/src/main/kotlin/com/sina/weibo/agent/plugin/SystemObjectProvider.kt
Replaced single global ConcurrentHashMap with per-project storage (projectObjects: ConcurrentHashMap<Project, ConcurrentHashMap<String, Any>>). Updated initialize(project), register(project, key, obj), get(project, key) signatures; added dispose(project) and disposeAll() methods for per-project resource cleanup.
API signature updates
jetbrains_plugin/src/main/kotlin/com/sina/weibo/agent/plugin/WecoderPlugin.kt, jetbrains_plugin/src/main/kotlin/com/sina/weibo/agent/ui/RunVSAgentToolWindowFactory.kt
Updated calls to SystemObjectProvider.register() and SystemObjectProvider.dispose() to pass project parameter as first argument, aligning with new per-project storage API.

Sequence Diagram

sequenceDiagram
    actor User
    participant IDE as IDE Instance
    participant Project1 as Project 1
    participant Project2 as Project 2
    participant SOP as SystemObjectProvider

    rect rgb(200, 220, 240)
    note over User,SOP: Old Behavior (Global)
    User->>IDE: Open Project 1
    IDE->>SOP: register("pluginService", obj1)
    SOP->>SOP: Store in global map
    User->>IDE: Open Project 2
    IDE->>SOP: register("pluginService", obj2)
    SOP->>SOP: Overwrite global map (conflict)
    end

    rect rgb(220, 240, 200)
    note over User,SOP: New Behavior (Per-Project)
    User->>IDE: Open Project 1
    IDE->>Project1: initialize()
    Project1->>SOP: register(project1, "pluginService", obj1)
    SOP->>SOP: Store in project1 map
    User->>IDE: Open Project 2
    IDE->>Project2: initialize()
    Project2->>SOP: register(project2, "pluginService", obj2)
    SOP->>SOP: Store in project2 map (isolated)
    User->>IDE: Close Project 1
    IDE->>SOP: dispose(project1)
    SOP->>SOP: Clean up project1 map only
    end
Loading

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~8 minutes

The changes follow a consistent, straightforward pattern: import removals are trivial, the SystemObjectProvider refactoring introduces clear per-project storage mechanics, and all caller updates simply add the project parameter in a uniform manner. No complex logic or error handling is introduced.

Poem

🐰 Multiple workspaces now live in harmony,
Per-project maps keep each one free,
No more conflicts or tangled threads,
Each project gets its own storage beds!
The plugin now scales, side by side—
Rabbit approves with cottontail pride! 🌿

Pre-merge checks and finishing touches

✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title Check ✅ Passed The pull request title "Fix for multiple workspaces not working" is directly related to the main objective of the changeset, which is to address the multiple workspaces issue described in linked issue #98. The title is concise, specific, and clearly communicates the primary change from the developer's perspective. A teammate scanning the commit history would immediately understand that this PR addresses the multiple workspaces problem in the plugin.
Linked Issues Check ✅ Passed The code changes successfully address the primary objectives from linked issue #98. The PR refactors SystemObjectProvider.kt to replace global singleton storage with per-project scoped storage using ConcurrentHashMap<Project, ConcurrentHashMap<String, Any>>, directly fixing the root cause where instance state was tied to a single Project [98]. The method signatures are updated to require a Project parameter (register, get, dispose), and WecoderPlugin.kt and RunVSAgentToolWindowFactory.kt are updated to pass the project context through these APIs [98]. This architecture shift ensures each workspace maintains its own correct state and UI without interference from other open projects [98].
Out of Scope Changes Check ✅ Passed All code changes are directly related to the multiple workspaces fix objectives. The core refactoring of SystemObjectProvider.kt to implement per-project storage is the primary change, while updates to WecoderPlugin.kt and RunVSAgentToolWindowFactory.kt reflect the necessary API adjustments to support per-project scoping. The removal of SystemObjectProvider imports from three files (MainThreadLanguageModelToolsShape.kt, MainThreadTaskShape.kt, MainThreadWindowShape.kt) appears to be cleanup resulting from the refactoring, as these files no longer require access to the service after the architectural change.
Docstring Coverage ✅ Passed Docstring coverage is 87.50% which is sufficient. The required threshold is 80.00%.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

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

@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: 0

🧹 Nitpick comments (1)
jetbrains_plugin/src/main/kotlin/com/sina/weibo/agent/plugin/SystemObjectProvider.kt (1)

69-69: Minor optimization: redundant clear() after remove().

The clear() call after remove() is technically redundant since the removed map will be garbage collected. However, this is harmless and may serve as defensive programming.

If you prefer a minor optimization, you can simplify to:

-        projectObjects.remove(project)?.clear()
+        projectObjects.remove(project)
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between ca32e3b and d820353.

📒 Files selected for processing (6)
  • jetbrains_plugin/src/main/kotlin/com/sina/weibo/agent/actors/MainThreadLanguageModelToolsShape.kt (0 hunks)
  • jetbrains_plugin/src/main/kotlin/com/sina/weibo/agent/actors/MainThreadTaskShape.kt (0 hunks)
  • jetbrains_plugin/src/main/kotlin/com/sina/weibo/agent/actors/MainThreadWindowShape.kt (0 hunks)
  • jetbrains_plugin/src/main/kotlin/com/sina/weibo/agent/plugin/SystemObjectProvider.kt (1 hunks)
  • jetbrains_plugin/src/main/kotlin/com/sina/weibo/agent/plugin/WecoderPlugin.kt (2 hunks)
  • jetbrains_plugin/src/main/kotlin/com/sina/weibo/agent/ui/RunVSAgentToolWindowFactory.kt (1 hunks)
💤 Files with no reviewable changes (3)
  • jetbrains_plugin/src/main/kotlin/com/sina/weibo/agent/actors/MainThreadLanguageModelToolsShape.kt
  • jetbrains_plugin/src/main/kotlin/com/sina/weibo/agent/actors/MainThreadTaskShape.kt
  • jetbrains_plugin/src/main/kotlin/com/sina/weibo/agent/actors/MainThreadWindowShape.kt
🔇 Additional comments (6)
jetbrains_plugin/src/main/kotlin/com/sina/weibo/agent/ui/RunVSAgentToolWindowFactory.kt (1)

1274-1274: Correct per-project disposal pattern.

The change correctly updates the disposal call to pass the project parameter, aligning with the new per-project lifecycle management approach in SystemObjectProvider.

jetbrains_plugin/src/main/kotlin/com/sina/weibo/agent/plugin/WecoderPlugin.kt (2)

144-144: Correct per-project disposal pattern.

The disposal call correctly passes the project parameter, ensuring project-specific resources are cleaned up when the project is disposed.


362-362: Correct per-project registration pattern.

The registration call correctly passes the project as the first parameter, storing the plugin service instance in project-scoped storage rather than global storage.

jetbrains_plugin/src/main/kotlin/com/sina/weibo/agent/plugin/SystemObjectProvider.kt (3)

19-20: Sound architecture change for per-project lifecycle.

The introduction of per-project storage using ConcurrentHashMap<Project, ConcurrentHashMap<String, Any>> correctly implements the per-project lifecycle pattern needed to support multiple workspaces simultaneously.


34-78: All SystemObjectProvider callsites updated to use per-project API
All initialize, register, get, and dispose calls now include the required project parameter; no legacy usages remain.


75-78: disposeAll() is defined but never invoked
SystemObjectProvider.disposeAll() clears all project entries but isn’t called anywhere. Remove it or invoke it during plugin/application shutdown (e.g., in your WecoderPlugin.dispose() or a similar lifecycle hook).

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.

Support for multiple workspaces open in one IntelliJ instance

1 participant