Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Conversation

@nekomeowww
Copy link
Member

@nekomeowww nekomeowww commented Nov 30, 2025

Description

  • Currently, stage-tamagotchi is multi-window / multi-tab architecture, means Chat window / Inlay window doesn't share the same Pinia with main window (which model renders at), this causes issue when syncing states between Pinia stores across windows.
  • The situation becomes more complex when it comes to play TTS audios if we use BroadcastChannel to send the syncing state patches, if no SharedWorker or election mechanism like Kubernetes involves, multiple windows / tabs with TTS configured, both chat streaming, TTS will play in the same time across these windows / tabs.
  • Here we introduce a BroadcastChannel & SharedWorker channel implemented for syncing states for windows / tabs first, then we should have another Pull Request, introduce another plugin or option to distinguish those Pinia stores with only one instance live, and use SharedWorker to dispatch messages only for the first constructor caller.

Linked Issues

Additional Context

@gemini-code-assist
Copy link
Contributor

Summary of Changes

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

This pull request addresses a critical state synchronization challenge in multi-window/multi-tab environments, particularly within the stage-tamagotchi and stage-web applications. By introducing a new Pinia plugin, @proj-airi/pinia-broadcast, it enables seamless sharing and updating of Pinia store states across different browser contexts. This prevents inconsistencies, such as duplicate audio playback, and ensures a unified user experience by keeping relevant application states, like the 'chat' store, in perfect harmony across all open windows or tabs.

Highlights

  • New Pinia Broadcast Plugin: Introduced @proj-airi/pinia-broadcast to synchronize Pinia store states across multiple browser windows or tabs.
  • Cross-Window State Sync: Implements state synchronization using BroadcastChannel and SharedWorker to maintain consistency in multi-window/multi-tab applications.
  • Targeted Store Integration: The plugin is specifically applied to the 'chat' Pinia store in both stage-tamagotchi and stage-web applications, with an environment-specific disablement for non-Electron runtimes.
  • Robust Transport Mechanism: Provides fallback to SharedWorker when BroadcastChannel is unavailable and includes options for custom transport, serialization, and initial state synchronization.
Using Gemini Code Assist

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

Invoking Gemini

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

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

Customization

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

Limitations & Feedback

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

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

Footnotes

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

Copy link
Contributor

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

Choose a reason for hiding this comment

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

Code Review

This pull request introduces a new package, @proj-airi/pinia-broadcast, to synchronize Pinia store state across different browser tabs and windows using BroadcastChannel and SharedWorker. The implementation is solid, providing a flexible transport mechanism and graceful fallbacks. I've identified a critical issue in the state patching logic that could lead to state desynchronization, and a high-severity configuration issue that disables the plugin in the web environment where it's most needed. My review includes suggestions to fix these issues.


applyingExternal = true
try {
context.store.$patch(() => Object.assign(context.store.$state, deserialize(message.state)))
Copy link
Contributor

Choose a reason for hiding this comment

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

critical

The current implementation of patching the store state using Object.assign can lead to state inconsistencies. Object.assign performs a shallow merge and does not remove properties that exist in the local state but not in the incoming state. This can cause state to diverge between tabs if properties are removed.

For example, if the state in one tab changes from { a: 1, b: 2 } to { a: 1 }, other tabs will receive { a: 1 } but Object.assign will not remove the b: 2 property, resulting in an incorrect state of { a: 1, b: 2 }.

A more robust way to apply the state is to use store.$patch() with the state object directly, which performs a deep patch. The function passed to $patch should also receive the state as an argument if you want to mutate it manually, which is not the case here.

I suggest replacing the current patching logic with a direct call to $patch.

Suggested change
context.store.$patch(() => Object.assign(context.store.$state, deserialize(message.state)))
context.store.$patch(deserialize(message.state))

Comment on lines +27 to +30
pinia.use(createBroadcastPlugin({
includeStore: ({ store }) => store.$id === 'chat',
disabled: import.meta.env.RUNTIME_ENVIRONMENT !== 'electron',
}))
Copy link
Contributor

Choose a reason for hiding this comment

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

high

The pinia-broadcast plugin is being disabled when the RUNTIME_ENVIRONMENT is not electron. For the stage-web application, this means the plugin will be disabled, preventing state synchronization across browser tabs, which seems to be one of the main goals of this feature. This condition was likely copied from the stage-tamagotchi (Electron app) configuration and is not appropriate for the web application. To enable cross-tab sync for the web app, this condition should be removed or adjusted.

pinia.use(createBroadcastPlugin({
  includeStore: ({ store }) => store.$id === 'chat',
}))

@github-actions
Copy link
Contributor

github-actions bot commented Nov 30, 2025

✅ Deploy to Cloudflare Workers (Preview) for stage-web ready!

Name Link
🔍 Latest deploy log https://github.com/moeru-ai/airi/actions/runs/210772011
😎 Deploy Preview https://d0aaa084-moeru-ai-airi.kwaa.workers.dev
🚀 Pull Request Preview https://pr-780-moeru-ai-airi.kwaa.workers.dev

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.

3 participants