Conversation
fix: show p-values alongside q-values in DE table
…ypes feat: metadata upload on all datatypes
- reports/images listed 6/2 candidate models each, but only choices[[1]] is ever selected since the model pickers are hidden for the bigomics-managed backend (appsettings_ui.R) - collapse both arrays to the single model that was actually running, removing the unused entries so the policy reflects reality
- swap reports + copilot_balanced to openrouter:deepseek/deepseek-v4-flash and copilot_deep to openrouter:openai/gpt-5.6-terra in the bigomics provider block of etc/ai_model_policy.json (images left unchanged) - update the test-appsettings-ai.R BigOmics assertions and test name to match the new ids so the fixture stops hardcoding the old gpt-5.4-nano/mini - refresh the stale copilot_run_controller.R tier-table comment naming the managed-backend models (omicsplayground-p6wk)
…omics" - copilot_restore_controller passed the "bigomics" sentinel straight to ovi_restore(), whose ovi_resolve_copilot_model() then hit the BYOK catalog branch and errored (ai_select_model has no "bigomics" provider), crashing restore of managed sessions - add .copilot_restore_provider(): map managed -> "openai" (drop key), pass a real BYOK provider + key through, mirroring .copilot_agent_build_args so restore resolves whatever provider/model the user has configured now - fix the restore-controller test bootstrap (unsourced .copilot_ai_provider) and cover managed + BYOK provider resolution
- deepseek-v4-flash and openai/gpt-5.6-terra only default reasoning_effort to medium as of omicsai 0.3.8; the old >=0.3.2 floor let a stale install silently resolve those models as plain chat, hard-erroring the first time reasoning_effort was passed explicitly (surfaced during the chores/update-ai-models design review)
- the standalone suite sources appsettings_server.R but not AuthenticationModule_functions.R, so every server-invoking test errored with "could not find function ai_byok_allowed" before reaching its assertions (shipped broken with the BYOK feature: 8 other app-globals are stubbed, this one was missed) - add the entitlement helper to the bootstrap block, mirroring the real definition exactly, so the 14 affected tests run their real code paths (make_auth leaves level unset -> "" -> BYOK allowed) - surfaced while reviewing chores/update-ai-models, which touches this file
- omicsai 0.3.8 added gpt-5.6-sol/terra/luna to its openai catalog; the openai provider policy only excludes gpt-5.5, so the three new models now legitimately appear in the reports/copilot menus alongside gpt-5.4-nano/mini and gpt-4o/gpt-4o-mini - update the two stale fixtures (live-catalog repopulate, and the empty-live-results fallback) to the new 7-item order rather than curating the models out of the policy - product decision: BYOK users get the extra choice
Chores/update ai models
The "Basic menu" switch (App settings) swapped the sidebar for a 5-tab
subset but changed nothing else: every board still showed its full
settings panel and every tab.
Menu
- basic_menu_tree keys now equal the tab name, so createMenu() emits a
flat sidebar item instead of a collapsible group holding one identical
child ("Cluster Samples > Cluster Samples").
Settings
- .advanced-option marks the blocks BASIC greys out: FDR/logFC and the
Options accordion on Differential expression and Geneset Enrichment,
the Options accordion on DataView and Pathway analysis. Driven by a
body.basic-mode class rather than shinyjs::disable() because the boards
are inserted lazily, after the toggle observer has already run, so a
disable() at toggle time would be lost.
- Greyed accordions are force-expanded: the settings are locked, but the
user should still see which ones are in effect.
- Differential expression shows only its Overview tab. !important because
tab_control() calls shiny::showTab(), which writes an inline display.
Switching to BASIC also resets the tabset, since the active tab may be
one that is about to be hidden.
Not included: skipping the load of boards unreachable in BASIC. Shiny
already suspends outputs in hidden elements (suspendWhenHidden defaults
TRUE) and bigdash's toggleTab fires the `hidden` event that drives it, so
the sibling boards in a module never render while their tab is inactive.
There is no rendering left to save there.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…options - basic menu is now DataView, Cluster Samples, Differential expression - Cluster Samples: grey out the "Filter options" and "Advanced options" accordions (hm_filter_accordion, hm_options_accordion) The .advanced-option markers on Geneset Enrichment and Pathway analysis stay: they are keyed on the body.basic-mode class, not on the menu, so they stay correct if either board returns to the basic menu. Inert until then. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
They stay collapsed as usual; only the grey-out remains. Takes the chevron rotate with it, which only existed to match the forced-open state. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Same treatment as Differential expression: Overview is the first panel of #dataview-tabs, so the existing selector just gains a second target. Switching to BASIC also resets the tabset, since the active tab may be one that is about to be hidden. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This reverts commit 4661ce3. Supervisor wants the greyed accordions expanded after all, so BASIC users can see which locked settings are in effect. Restores the forced-open rule and the matching chevron rotate. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
- generate AI text reports (de, pathways) and infographics (combined, de, pathways) into pgx$ai via playbase::pgx.update_reports() / pgx.update_infographics(), filling slots that were never populated for the bundled example dataset - wgcna report generation failed on this dataset (playbase bug, tracked separately) and was skipped rather than aborting the batch
Plotly plots for Qsee
fix(home): stop the launcher overflowing on 14" laptops
Gate DataView Settings tab behind DEVMODE
…launcher dev-gate
The single "app" OPG instance's sidebar DOM is built once per session
by opg_ui()'s createMenu() -- opg_server.R's tab_control() only
shows/hides those existing nodes at runtime (bigdash.filterTabs()), it
can't turn a collapsible group into flat items or back. So an earlier
attempt to promote MultiOmics's own boards (MOFA, multiGSEA, SNF, ...)
out of their collapsible "MultiOmics" submenu by only changing
opg_multiomics_menu_tree() (opg_server.R's reactive filtering tree)
never reached the DOM: ui.R's opg_ui("app") call still built the
sidebar from the plain, grouped opg_menu_tree().
- opg_ui.R: extract the promotion into opg_promote_multiomics(), a
general helper that splits any tree's "MultiOmics" group into flat,
single-board entries at the same position, leaving every other
group (and its key name) untouched -- opg_menu_tree() itself stays
unchanged, so admin_ui.R's Basic Menu picker (which labels boards
"<GroupName> - <BoardTitle>" off opg_menu_tree()'s own keys) still
shows "MultiOmics - LASAGNA" etc. rather than per-board group names.
opg_multiomics_menu_tree() now just builds its restricted subset and
reuses the same helper.
- ui.R: opg_ui("app", ...) now passes
menu_tree = opg_promote_multiomics(opg_menu_tree()) -- this is what
actually builds the sidebar DOM, so the flat layout applies to both
the Playground and MultiOmics views alike (board visibility is still
separately gated by tab_control()'s dataset-datatype check, so
MultiOmics boards still only show for multi-omics datasets).
- launcher_server.R: launch_multiomics no longer shows the
"Developers only!" alert or requires opt$DEVMODE.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Cag8uYDzGgwXxseRgfwLmf
…sidebar divider Switching between the MultiOmics and Playground views left a visibly thicker line between SystemsBio and Standard WGCNA -- traced to two separate bugs in the same area: 1. opg_server.R has two independent observers that both call tab_control(): one keyed on env$trigger_on_change_dataset() (fires once the new dataset is actually loaded) and one keyed on menu_tree() alone. opg_view() -- and so menu_tree() -- flips the instant a launcher tile is clicked, well before PGX$X/PGX$datatype catch up to the dataset that eventually loads to match it. The menu_tree()-only observer therefore fired tab_control() once right on that flip, computing a keep-list from the *new* view against the *still-old* dataset (e.g. showing every SystemsBio/WGCNA board at once) before the dataset-load observer corrected it a moment later. Guarded it to skip while the loaded dataset's type doesn't match the current view -- safe either way, since the other observer re-runs tab_control() once a matching dataset actually loads. 2. The real, persistent culprit: bigdash.showTabs(session) (called once a dataset finishes loading) fires bigdash's client-side 'show-tabs' message, which blanket-shows every direct child of .sidebar-content (anything not .collapse/.nodisp) after its own 1s delay. That includes a flat, individually-filtered sidebarItem()'s own <hr> divider (a direct child) even though its nested <p class="tab-trigger"> (one level deeper, untouched by that blanket pass) correctly stays hidden -- silently re-showing the divider for an item tab_control() had just hidden (e.g. a MultiOmics board while viewing a single-omics dataset), until some unrelated tab_control() run happened to fix it. Re-run tab_control() just after that delay elapses so the two stay in sync. Confirmed via jQuery show/hide/toggle instrumentation and repeated live cycles (Playground <-> MultiOmics, mox-brca <-> example-data) that the divider stays a single, uniform-thickness line throughout. No changes to the bigdash package itself. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Cag8uYDzGgwXxseRgfwLmf
ui.R has no uiOutput("current_dataset") (or any navheader-style div)
anywhere -- this output, its dataset_click observer, and the
removeUI(selector = "#current_dataset > #spinner-container") cleanup
call never had anything to render into or select. The actual
dataset-name popup users see comes entirely from
components/ui/ui-omicsboard.R's OmicsBoardUI()/OmicsBoard() pair,
which every board wires up through its own namespaced
uiOutput(ns("current_dataset")).
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Cag8uYDzGgwXxseRgfwLmf
pgx$wgcna$report$infographic/$bullets (the old ai-old-wgcnareport.R schema) is never populated by the current pipeline -- nothing calls those generator functions anymore -- so the popup's infographic branch was permanently dead, always falling through to the plain pgx.info() text popup. Point it at pgx$ai$combined$infographic instead: the v1 AI-report schema (playbase::pgx.update_infographics(), ai-infographics.R), where "combined" is the dataset-wide report -- labelled "Summary" in AI Studio's own infographic tab (.AI_INFOGRAPHIC_LABELS). That field holds raw PNG bytes plus a status/error, not a decoded raster array, so decode via png::readPNG() (which accepts a raw vector directly) before handing it to ui.showImageModal(), which still expects one. Falls back to the text-info popup whenever the infographic is missing, not yet generated, errored, or fails to decode. The old schema's short "bullets" field (a few summary lines meant for the modal footer) has no equivalent in the new one -- pgx$ai$combined $report is a full multi-section markdown write-up, not caption-sized -- so the footer is now just a static "Summary infographic" label. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Cag8uYDzGgwXxseRgfwLmf
Adds a small, generic modal helper -- ui.showTabsetModal(tabs, ...) in ui-modalUI.R -- that lays out a named list of tab title -> UI content as a bslib::navset_tab() inside modalDialog2(). A single-tab list skips the tab switcher entirely and shows that one tab's content directly, since there's nothing to switch between. Factored the image-embedding half of ui.showImageModal() out into ui.imageTag() (ui-startupModal.R) -- a raster array to a base64 <img> tag -- so it can be reused as one tab's content without going through a whole separate modal. The dataset-name popup (ui-omicsboard.R) now uses ui.showTabsetModal() with an "Infographic" tab (pgx$ai$combined$infographic, decoded via png::readPNG()) plus an "Info" tab (playbase::pgx.info()) when an infographic is available, or just the "Info" tab alone -- rendered without a tab switcher -- when it isn't. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Cag8uYDzGgwXxseRgfwLmf
Switching tabs previously resized the whole modal to whatever the newly-active tab's content happened to need. ui.showTabsetModal() now wraps its tab area in a fixed-height, scrollable box (body_height, default "65vh") whenever there's more than one tab -- the same box regardless of which tab is showing, so the dialog itself never moves. A single-tab modal is untouched (nothing to switch between). ui.imageTag() gains a fit=TRUE mode: instead of a fixed pixel width with height following the image's own aspect ratio, it scales via CSS (max-width:100%, object-fit:contain) to fit whatever space it's dropped into, capped by an explicit max_height (matched to the tabset's body_height -- a CSS percentage-height chain down through bslib's own tab-panel wrapper divs isn't guaranteed, so this uses the same fixed value on both ends instead of relying on one). The dataset-name popup's Infographic tab now uses fit=TRUE with the same body_height passed to ui.showTabsetModal(), so the infographic scales to fill the fixed tab area instead of rendering at a flat 1000px width. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Cag8uYDzGgwXxseRgfwLmf
- force the session consent to FALSE whenever the AI config is locked or the deployment is unlicensed, in the login seed and the write observer as well as the greying observer: a disabled switch keeps whatever value it had, so a user who opted in before the lock stayed opted in behind a control they could no longer reach. The stored record is left untouched, since a deployment lock is not the user withdrawing - pass the live consent into ovi_restore() on both the async and sync restore paths, reading it from .copilot_ai_provider rather than the restore-time provider, which has already been rewritten to ovi's "openai" sentinel and so would never have matched "bigomics" - reword the switch to name the party that actually trains: BigOmics trains no models, what the toggle widens is which upstream providers may be routed to - raised in review of #1885
body_height was wrapping the entire navset (tab-header row plus content), so the actual content area each tab's own box gave was body_height minus however tall the tab-header row happened to be. An image fit against the full body_height value (as the dataset-name popup's Infographic tab does) then overflowed that smaller real box by exactly the header's height, forcing a vertical scrollbar even though the image itself never exceeded the intended box. Wrap each tab's own content in the fixed height/width box instead, so the tab-header row sits above it unaffected and every tab's content area is identically sized (both dimensions) regardless of which tab is active -- and an image capped at the same body_height value now actually fits within its real box. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Cag8uYDzGgwXxseRgfwLmf
Same dead-schema issue as the dataset-name popup: pgx$wgcna$report $bullets/$infographic (ai-old-wgcnareport.R) is never populated by the current pipeline. Points bullet_points and image.RENDER() at the v1 schema's "combined" slot instead -- the dataset-wide report, labelled "Summary" in AI Studio's own infographic tab -- via pgx$ai$combined $report and pgx$ai$combined$infographic$bytes. image.RENDER() writes the infographic straight to its tempfile with writeBin() rather than png::readPNG() + png::writePNG(): the new schema already stores raw PNG bytes (not a decoded raster array), so the old decode/re-encode round trip is no longer needed. Also guards on infographic$status == "done" and non-empty bytes, matching the popup's fallback behavior for a missing/errored/in-progress entry. (SummaryBoardUI()/SummaryBoard() are only source()d by 00SourceAll.R -- nothing currently mounts this board in any nav_panel or board registry -- so this fixes the schema without addressing that.) Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Cag8uYDzGgwXxseRgfwLmf
…tent Constraining each tab's own content to width:100% (previous commit) wasn't enough -- .modal-dialog itself only gets a max-width from its size class (e.g. modal-xl), not a fixed width, so the dialog still sized to whichever tab's content happened to be active (a narrower image vs. a full-width text panel) and visibly changed width when switching tabs. modalDialog2() gains a dialog_style param applied directly to .modal-dialog; ui.showTabsetModal() passes dialog_style="width:100%;" whenever there's more than one tab, pinning the dialog to its size class's max-width consistently regardless of which tab is showing. Single-tab modals (and every other modalDialog2() caller) are unaffected -- dialog_style defaults to NULL. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Cag8uYDzGgwXxseRgfwLmf
Pulls Highlights, Overview, and Conclusion out of the combined
report's markdown (pgx$ai$combined$report) via the new
playbase::ai_report_get_section(), one sub-heading per section, with
a small disclaimer at the bottom ("generated by AI and may contain
inaccuracies"). "Conclusion" (singular) is the canonical heading
name the combined-report prompt actually produces (omicsai's
inst/prompts/combined/combined_report_rules.md), not "Conclusions".
The tab is only added when at least one of the three sections is
actually present -- same pattern as the Infographic tab -- so a
dataset with no AI report yet still shows just Info (or
Infographic + Info). Tab order is now Infographic, AI summary, Info,
whichever apply.
Verified the section-pulling/rendering logic (all three sections
present, a partial report with only one section, no report, and a
report with none of the three headings) against a standalone copy of
ai_report_get_section(), since the installed playbase package doesn't
have the function yet -- it needs a package rebuild from
/home/kwee/Playground/repo/playbase (uncommitted there) before this
tab will actually populate in a running app.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Cag8uYDzGgwXxseRgfwLmf
Was just trailing right after the section text via a normal hr()/div, so it floated wherever the sections happened to end rather than sitting at the bottom of the tab's fixed-height box. Wraps the tab in a flex column (min-height:100%, filling ui.showTabsetModal()'s body_height) with margin-top:auto on the disclaimer block, pinning it to the bottom regardless of how much section text sits above it. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Cag8uYDzGgwXxseRgfwLmf
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Cag8uYDzGgwXxseRgfwLmf
feat: add per-user consent for AI conversation data sharing
fix(ui): dataset-name popup — v1 AI schema, tabset modal, AI summary tab
feat: multi-omics launcher
- point Copilot's data_dir at auth$user_dir, the same base its chats and uploaded docs already derive from, instead of the shared PGX.DIR root - the app writes a user's .pgx files under auth$user_dir, so scanning the root turned up only other users' folders and datasets went unfound
- auth already applies the ENABLE_USERDIR rule and every dataset write path agrees with its answer, so re-deriving <pgx_dir>/<email> aimed at an empty folder whenever that flag was off or under apache-cookie auth - keep the per-email override for chats and uploaded docs, which Copilot creates itself and which need no pre-existing content
- 0.5.95 re-pins the dataset directory before each listing forward; on older builds the per-user data_dir introduced here would let one session's listing return another user's dataset names
Fix/user dir
Conflicts resolved: - docker/Dockerfile.update: kept both sides' package installs (plotly.repel from edgy, WGCNAplus/isotree/collapse from master) - VERSION, CHANGELOG*.md, FEATURES.md: kept edgy's generated files; they are a superset of master's (same tag sections plus 5.0-rc1) and match what `make changelog` produces on the current script. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EXtDC1prGoyKe4cYf2hTSE
Conflict resolutions: - VERSION: keep edgy's 5.0-rc1+edgy260831 - components/board.pcsf/R/util_pcsf.R: edgy deleted the file as dead code, but devel's #1789 added pcsf.write_cx2() there and the PCSF panels call it. Restore the file with only pcsf.write_cx2(); visplot.PCSF() and plot.pcsf.NOTUSED() stay deleted (unreferenced in edgy). - components/ui/ui-PlotModule.R: stays deleted; PlotModuleServer now lives in bigdash. devel's download.handlers argument (used by the new CX2 export) is ported there in bigomics/bigdash#47. - components/board.upload/R/upload_module_preview_counts.R: keep edgy's unconditional datapath[1] (the filename gate was removed on purpose in d95d6a4) and layer devel's hPTM additions on top. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01TwCeAfAF9p965ed6nZUVjx
Qsee/Bsee, Across and Mythril are badged "soon" on the launcher; the popup now carries a notify-me link to the matching HubSpot form instead of a dead end. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01TwCeAfAF9p965ed6nZUVjx
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
PR for edgy release