Skip to content

feat: Map plugin_data by persona_name - #12481

Open
undivisible wants to merge 2 commits into
mainfrom
map-plugin-data-by-persona-name-417711359684236132
Open

feat: Map plugin_data by persona_name#12481
undivisible wants to merge 2 commits into
mainfrom
map-plugin-data-by-persona-name-417711359684236132

Conversation

@undivisible

@undivisible undivisible commented Aug 31, 2026

Copy link
Copy Markdown
Collaborator

Implemented the logic to map plugin_data by persona_name into a local json file, as requested by the TODO item in backend/scripts/web.py.

Failure-Class: none


PR created automatically by Jules for task 417711359684236132 started by @undivisible

Review in cubic


Note

Low Risk
Offline analytics script changes only; no production API or auth paths, with exports confined to a gitignored data folder.

Overview
Adds get_plugin_data_by_persona_name(), which streams Firestore plugins_data, keeps docs with a persona capability and a username, and writes a username-keyed map to backend/scripts/data/plugin_data_by_persona_name.json.

get_user_messages_with_bot_name() now writes its export to the same backend/scripts/data/ directory instead of the script working directory. The __main__ block runs the new export after the messages dump, replacing the prior TODO.

Reviewed by Cursor Bugbot for commit 1d61495. Configure here.

Resolves the TODO in `backend/scripts/web.py` to map all plugin_data by persona_name so that it can be locally mapped via json.
Adds a new function `get_plugin_data_by_persona_name()` that iterates over all items in the `plugins_data` collection, mapping them using the `name` field as the key, and outputting to `plugin_data_by_persona_name.json`.

Co-authored-by: google-labs-jules[bot] <161369871+google-labs-jules[bot]@users.noreply.github.com>
@google-labs-jules

Copy link
Copy Markdown
Contributor

👋 Jules, reporting for duty! I'm here to lend a hand with this pull request.

When you start a review, I'll add a 👀 emoji to each comment to let you know I've read it. I'll focus on feedback directed at me and will do my best to stay out of conversations between you and other bots or reviewers to keep the noise down.

I'll push a commit with your requested changes shortly after. Please note there might be a delay between these steps, but rest assured I'm on the job!

For more direct control, you can switch me to Reactive Mode. When this mode is on, I will only act on comments where you specifically mention me with @jules. You can find this option in the Pull Request section of your global Jules UI settings. You can always switch back!

New to Jules? Learn more at jules.google/docs.


For security, I will only act on instructions from the user who triggered this task.

@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Aug 31, 2026

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review Completed 2026-08-31T16:51:57.084220Z 5c96314 PR opened
ℹ️ 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" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

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

Copy link
Copy Markdown

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.

Reviewed commit: 5c9631498b

ℹ️ 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 thread backend/scripts/web.py

def get_plugin_data_by_persona_name() -> None:
plugin_data_by_name: Dict[str, Dict[str, Any]] = {}
plugins_ref = db.collection("plugins_data").stream()

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Resolve the Firestore client at call time

This new read uses the legacy global db proxy, so the helper bypasses the repository's call-time client seam and cannot accept an explicitly selected or injected Firestore client. Import get_firestore_client() and resolve it inside this function instead.

AGENTS.md reference: backend/AGENTS.md:L169-L171

Useful? React with 👍 / 👎.

Comment thread backend/scripts/web.py Outdated
data: Dict[str, Any] = cast(Dict[str, Any], raw) if isinstance(raw, dict) else {}
name = data.get("name")
if name:
plugin_data_by_name[name] = data

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Preserve every document that shares a persona name

When two persona documents have the same display name, this assignment silently replaces the first document with the later one, so the generated file does not contain all plugin data. This is a supported case because persona creation uniquifies username but accepts duplicate name values; group documents under each name or use a unique identifier rather than storing a single value.

Useful? React with 👍 / 👎.

Comment thread backend/scripts/web.py Outdated
Comment on lines +20 to +21
with open("plugin_data_by_persona_name.json", "w") as f:
json.dump(plugin_data_by_name, f, default=str)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Keep the sensitive export outside tracked paths

When this script is run from either the repository root or backend/, the output path is not covered by .gitignore, and the complete plugin documents can include owner email addresses, persona/chat/memory prompts, Twitter data, and integration configuration. This leaves a sensitive untracked artifact that a routine broad git add can commit; write it beneath an ignored data directory or add a precise ignore entry for this generated file.

Useful? React with 👍 / 👎.

Comment thread backend/scripts/web.py
import json


def get_plugin_data_by_persona_name() -> None:

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Add behavioral coverage for the new export

This commit adds a new Firestore-to-JSON feature without adding any test for its core mapping behavior or its main error cases, such as absent or duplicate names. Add a hermetic test using an injected fake client and a temporary output directory so regressions in the generated mapping are caught by the backend suite.

AGENTS.md reference: AGENTS.md:L28-L33

Useful? React with 👍 / 👎.

@Git-on-my-level Git-on-my-level left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Thanks for picking up this TODO — the new get_plugin_data_by_persona_name() in backend/scripts/web.py mirrors the existing get_user_messages_with_bot_name() style nicely (same defensive cast(...) if isinstance(raw, dict) handling, same json.dump(..., default=str)), and the needed typing imports were already in place. Requesting changes for three things that affect what this export actually produces before it gets run against real data:

  1. Duplicate name silently drops documents. plugin_data_by_name[name] = data is last-write-wins, and nothing in the schema makes name unique — username is the uniquified persona handle (see get_persona_by_username_db in backend/database/apps.py, which filters on username + capabilities array_contains 'persona'), while name is a free-form display name. The TODO asks to map all plugin_data, so an overwrite here quietly skews any analysis built on this file. Please preserve all docs for a shared name (e.g. key by username, or keep a list per name / disambiguate with the doc id).

  2. Scope vs. function name. plugins_data is the apps collection (apps_collection = 'plugins_data' in backend/database/apps.py), so this streams every app, not just personas, and keys them by display name. If the goal is persona analysis, a capabilities array_contains 'persona' filter would match the ..._by_persona_name name; otherwise consider renaming to reflect that it maps all plugin docs by display name.

  3. Output path sits in tracked territory. plugin_data_by_persona_name.json is written to the CWD and isn't covered by .gitignore — the ignored script outputs live under backend/scripts/rag/*.json, /backend/scripts/data/, and backend/scripts/stt/diarization.json. These documents can carry owner emails, persona/chat prompts, and integration config, so an accidental git add -A after a run would commit user data. /backend/scripts/data/ already exists and is ignored — writing there (or gitignoring the filename) fixes it. The pre-existing user_messages_with_bot_name.json write has the same exposure and could get the same one-line fix while you're in here.

Minor, non-blocking: newer scripts (e.g. backend/scripts/chat_agent_cost_report.py, backend/scripts/backfill_mcp_key_full_access.py) resolve Firestore via get_firestore_client() at call time rather than the legacy global db; fine to defer since this file already uses db throughout.

No test demanded for this to land — it's a manual analytics script — but a tiny hermetic test for the duplicate-name handling would be welcome if you want one. Once the collision handling and output location are sorted this should be quick to re-review.


by AI on behalf of David — if you need David’s attention urgently, please @Git-on-my-level and escalate with need human response.

@kodjima33 kodjima33 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Approve only: feature (plugin_data by persona_name script, duplicate of #12489), not a bug fix — stays approve-only per policy.

username is the uniquified handle so duplicate display names no longer
drop documents. JSON output goes to the gitignored scripts/data dir.
@Git-on-my-level

Copy link
Copy Markdown
Collaborator

Owner approval acknowledged — leaving this as a comment rather than another change request, since the remaining items are non-blocking for a manual analytics script.

New information from comparing the two PRs implementing this TODO: this one is the functionally correct one. get_plugin_data_by_persona_name() keys the export on name, which persona creation actually writes (backend/routers/apps.py:901–917 stores display name plus the uniquified username), and it reads the right collection (apps_collection = 'plugins_data', backend/database/apps.py:35). The sibling #12489 instead keys on persona_name, a field no production path writes (it exists only as a parameter of generate_persona_desc() in backend/utils/apps.py:882), so its export would come out empty, and it also adds stray fix_web.patch/fix_web2.patch files at the repo root. Since both PRs modify the same hunk of backend/scripts/web.py from the same base, only one can merge cleanly — if you keep one, this is the one to keep (the sibling would need its key field fixed otherwise).

Two non-blocking caveats from the earlier review worth keeping in mind when the script is actually run:

  • Two personas sharing a display name overwrite each other in the dict (last-write-wins); username is the unique handle if the analysis ever needs disambiguation.
  • plugin_data_by_persona_name.json lands in the CWD and isn't covered by .gitignore; these docs can carry owner emails and persona/chat prompts, so writing under /backend/scripts/data/ (already ignored) is the safer spot.

Either way, a maintainer call on which duplicate lands is the only thing left before merge.


by AI on behalf of David — if you need David’s attention urgently, please @Git-on-my-level and escalate with need human response.

@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.

@undivisible

Copy link
Copy Markdown
Collaborator Author

CR follow-up: key persona plugin_data by username (the uniquified handle) so duplicate display names no longer drop documents, and write JSON under the gitignored scripts/data dir.

@cursor

cursor Bot commented Sep 2, 2026

Copy link
Copy Markdown

Bugbot couldn't run - usage limit reached

Bugbot is counted against Cursor usage for this user or team, and this run hit a usage or spend limit.

A user or team admin can review and increase usage limits in the Cursor dashboard.

(requestId: serverGenReqId_8a9b6015-0be8-459f-b886-09657ab4905e)

@Git-on-my-level
Git-on-my-level dismissed their stale review September 2, 2026 02:47

Resolved at 1d61495: export now keys on the uniquified username via setdefault (duplicate display names no longer drop docs), filters to persona-capability docs, and writes both JSON outputs under the gitignored backend/scripts/data/ directory.

@Git-on-my-level

Copy link
Copy Markdown
Collaborator

Thanks for the follow-up — all three items from the earlier change request are resolved at 1d61495, verified against backend/scripts/web.py:

  1. Keying. plugin_data_by_username.setdefault(str(username), data) now keys on the uniquified handle that persona creation actually writes (increment_username, backend/routers/apps.py:1039–1051), so duplicate display names no longer drop documents — and setdefault keeps the first doc if a handle ever repeats.
  2. Scope. The capabilities check (if isinstance(capabilities, list) and "persona" not in capabilities: continue) restricts the export to persona docs, matching the function name.
  3. Output. Both writes now target backend/scripts/data/ (Path(__file__).resolve().parent / "data" with mkdir(parents=True, exist_ok=True)), covered by .gitignore via /backend/scripts/data/ — this also fixes the pre-existing user_messages_with_bot_name.json exposure, and the docstring documenting the why is a nice touch.

The earlier change request is dismissed as resolved. The one call still open before merge is the routine maintainer choice between this PR and sibling #12489 (same TODO, same hunk) — this one remains the functionally correct implementation.


by AI on behalf of David — if you need David’s attention urgently, please @Git-on-my-level and escalate with need human response.

@Git-on-my-level Git-on-my-level added the positive-signal Good PR — positive signal, not a formal approval label Sep 2, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

positive-signal Good PR — positive signal, not a formal approval python

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants