Repository navigation
feat(web-ui): session polish, persist sub-tab nav, provider health dashboard, v0.0.30 #161
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 1 commit
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -69,10 +69,14 @@ | |
| const mainTab = typeof mainTabSource === 'string' ? mainTabSource.trim().toLowerCase() : ''; | ||
| const configMode = typeof configModeSource === 'string' ? configModeSource.trim().toLowerCase() : ''; | ||
| const settingsTab = typeof vm.settingsTab === 'string' ? vm.settingsTab.trim().toLowerCase() : 'general'; | ||
| const skillsTargetApp = typeof vm.skillsTargetApp === 'string' && (vm.skillsTargetApp === 'codex' || vm.skillsTargetApp === 'claude') ? vm.skillsTargetApp : 'codex'; | ||
| const promptTemplatesMode = typeof vm.promptTemplatesMode === 'string' && (vm.promptTemplatesMode === 'compose' || vm.promptTemplatesMode === 'manage') ? vm.promptTemplatesMode : 'compose'; | ||
| const snapshot = { | ||
| settingsTab: settingsTab === 'data' ? 'data' : 'general', | ||
| mainTab: MAIN_TAB_SET.has(mainTab) ? mainTab : 'dashboard', | ||
| configMode: configModeSet && configModeSet.has(configMode) ? configMode : 'codex' | ||
| configMode: configModeSet && configModeSet.has(configMode) ? configMode : 'codex', | ||
| skillsTargetApp, | ||
| promptTemplatesMode | ||
| }; | ||
| try { | ||
| localStorage.setItem(NAV_STATE_STORAGE_KEY, JSON.stringify(snapshot)); | ||
|
|
@@ -99,7 +103,13 @@ | |
| ? restored.settingsTab.trim().toLowerCase() | ||
| : ''; | ||
| const shouldUpdateSettingsTab = !!(nextSettingsTab && (nextSettingsTab === 'general' || nextSettingsTab === 'data') && nextSettingsTab !== this.settingsTab); | ||
| if (!shouldUpdateConfigMode && !shouldUpdateMainTab && !shouldUpdateSettingsTab) { | ||
| const nextSkillsTargetApp = restored && typeof restored.skillsTargetApp === 'string' && (restored.skillsTargetApp === 'codex' || restored.skillsTargetApp === 'claude') | ||
| ? restored.skillsTargetApp : ''; | ||
| const shouldUpdateSkillsTargetApp = !!(nextSkillsTargetApp && nextSkillsTargetApp !== this.skillsTargetApp); | ||
| const nextPromptTemplatesMode = restored && typeof restored.promptTemplatesMode === 'string' && (restored.promptTemplatesMode === 'compose' || restored.promptTemplatesMode === 'manage') | ||
| ? restored.promptTemplatesMode : ''; | ||
| const shouldUpdatePromptTemplatesMode = !!(nextPromptTemplatesMode && nextPromptTemplatesMode !== this.promptTemplatesMode); | ||
| if (!shouldUpdateConfigMode && !shouldUpdateMainTab && !shouldUpdateSettingsTab && !shouldUpdateSkillsTargetApp && !shouldUpdatePromptTemplatesMode) { | ||
| return false; | ||
| } | ||
| this.__navStateRestoring = true; | ||
|
|
@@ -113,6 +123,12 @@ | |
| if (shouldUpdateMainTab) { | ||
| this.switchMainTab(nextMainTab); | ||
| } | ||
| if (shouldUpdateSkillsTargetApp) { | ||
| this.skillsTargetApp = nextSkillsTargetApp; | ||
| } | ||
| if (shouldUpdatePromptTemplatesMode) { | ||
| this.promptTemplatesMode = nextPromptTemplatesMode; | ||
| } | ||
| } finally { | ||
| this.__navStateRestoring = false; | ||
| } | ||
|
|
@@ -674,10 +690,7 @@ | |
| ? this.activeSessionMessages.length | ||
| : 0; | ||
| if (total <= 0) return; | ||
| const baseSize = Number.isFinite(this.sessionPreviewInitialBatchSize) | ||
| ? Math.max(1, Math.floor(this.sessionPreviewInitialBatchSize)) | ||
| : 40; | ||
| this.sessionPreviewVisibleCount = Math.min(baseSize, total); | ||
| this.sessionPreviewVisibleCount = total; | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Removing message batching may cause rendering performance issues for large sessions. Previously, For a session with 300+ messages (now the default initial load), this could cause:
The PR summary mentions "display all fetched session messages immediately," but consider whether progressive rendering (even if automatic/invisible) would provide better UX for huge sessions. Possible mitigation: Virtual scrolling or windowingIf large sessions become a performance bottleneck, consider implementing virtual scrolling (render only visible messages) using a library like For now, monitor performance with sessions containing 300+ messages. 🤖 Prompt for AI Agents |
||
| this.invalidateSessionTimelineMeasurementCache(); | ||
| }, | ||
|
|
||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -187,9 +187,7 @@ export function switchMainTab(tab) { | |
| void Promise.resolve(marketOverviewLoad).catch(() => {}); | ||
| } | ||
| if (enteringPluginsTab && typeof this.loadPluginsOverview === 'function') { | ||
| // Default behavior: always land on Prompt Templates + Compose when entering Plugins. | ||
| this.pluginsActiveId = 'prompt-templates'; | ||
| this.promptTemplatesMode = 'compose'; | ||
| this.promptComposerPickerVisible = false; | ||
| let pluginsLoad = null; | ||
| try { | ||
|
|
@@ -456,6 +454,26 @@ export async function loadActiveSessionDetail(api, options = {}) { | |
| } | ||
| } | ||
| this.sessionPreviewPendingVisibleCount = 0; | ||
| if (this.activeSessionDetailClipped) { | ||
| const autoFetchSession = currentActiveSession; | ||
| this.$nextTick(() => { | ||
| if (this.activeSession !== autoFetchSession) return; | ||
| if (this.sessionDetailLoading) return; | ||
| if (!this.activeSessionDetailClipped) return; | ||
| const currentLimit = Number(this.sessionDetailMessageLimit); | ||
| const fetchStep = Number.isFinite(this.sessionDetailFetchStep) | ||
| ? Math.max(1, Math.floor(this.sessionDetailFetchStep)) | ||
| : 300; | ||
| const limitCap = Number.isFinite(this.sessionDetailMessageLimitCap) | ||
| ? Math.max(1, Math.floor(this.sessionDetailMessageLimitCap)) | ||
| : 1000; | ||
| const nextLimit = Math.min(currentLimit + fetchStep, limitCap); | ||
| if (nextLimit <= currentLimit) return; | ||
| this.sessionDetailMessageLimit = nextLimit; | ||
| this.sessionPreviewPendingVisibleCount = nextLimit; | ||
| void this.loadActiveSessionDetail({ preserveVisibleCount: true }); | ||
| }); | ||
| } | ||
|
Comment on lines
+457
to
+476
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Auto-fetch recursion may trigger rapid sequential API calls for large clipped sessions. When
This results in 4 rapid sequential API calls with no delay between them. Potential issues:
Consider:
Example: Add delay between auto-fetches if (this.activeSessionDetailClipped) {
const autoFetchSession = currentActiveSession;
- this.$nextTick(() => {
+ setTimeout(() => {
if (this.activeSession !== autoFetchSession) return;
if (this.sessionDetailLoading) return;
if (!this.activeSessionDetailClipped) return;
const currentLimit = Number(this.sessionDetailMessageLimit);
const fetchStep = Number.isFinite(this.sessionDetailFetchStep)
? Math.max(1, Math.floor(this.sessionDetailFetchStep))
: 300;
const limitCap = Number.isFinite(this.sessionDetailMessageLimitCap)
? Math.max(1, Math.floor(this.sessionDetailMessageLimitCap))
: 1000;
const nextLimit = Math.min(currentLimit + fetchStep, limitCap);
if (nextLimit <= currentLimit) return;
this.sessionDetailMessageLimit = nextLimit;
this.sessionPreviewPendingVisibleCount = nextLimit;
void this.loadActiveSessionDetail({ preserveVisibleCount: true });
- });
+ }, 200);
}🤖 Prompt for AI Agents |
||
| this.$nextTick(() => { | ||
| if (this.mainTab !== 'sessions' || !this.sessionPreviewRenderEnabled) { | ||
| return; | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 Analysis chain
🏁 Script executed:
Repository: SakuraByteCore/codexmate
Length of output: 152
🏁 Script executed:
Repository: SakuraByteCore/codexmate
Length of output: 84
🏁 Script executed:
Repository: SakuraByteCore/codexmate
Length of output: 97
🏁 Script executed:
Repository: SakuraByteCore/codexmate
Length of output: 726
🏁 Script executed:
Repository: SakuraByteCore/codexmate
Length of output: 831
🏁 Script executed:
Repository: SakuraByteCore/codexmate
Length of output: 1731
🏁 Script executed:
Repository: SakuraByteCore/codexmate
Length of output: 96
🏁 Script executed:
Repository: SakuraByteCore/codexmate
Length of output: 3766
🏁 Script executed:
# Check git history for the change from 80 to 300 git log --oneline -n 20 -- ./web-ui/app.jsRepository: SakuraByteCore/codexmate
Length of output: 154
🏁 Script executed:
Repository: SakuraByteCore/codexmate
Length of output: 6160
🏁 Script executed:
# Look at git diff for the commit that changed these lines git show 349a50e --statRepository: SakuraByteCore/codexmate
Length of output: 17245
🏁 Script executed:
Repository: SakuraByteCore/codexmate
Length of output: 5272
🏁 Script executed:
Repository: SakuraByteCore/codexmate
Length of output: 490
🏁 Script executed:
Repository: SakuraByteCore/codexmate
Length of output: 3077
🏁 Script executed:
Repository: SakuraByteCore/codexmate
Length of output: 50
🏁 Script executed:
Repository: SakuraByteCore/codexmate
Length of output: 3785
🏁 Script executed:
Repository: SakuraByteCore/codexmate
Length of output: 1155
🏁 Script executed:
Repository: SakuraByteCore/codexmate
Length of output: 1433
🏁 Script executed:
Repository: SakuraByteCore/codexmate
Length of output: 308
🏁 Script executed:
Repository: SakuraByteCore/codexmate
Length of output: 685
🏁 Script executed:
Repository: SakuraByteCore/codexmate
Length of output: 2200
🏁 Script executed:
Repository: SakuraByteCore/codexmate
Length of output: 5493
🏁 Script executed:
Repository: SakuraByteCore/codexmate
Length of output: 1416
🏁 Script executed:
Repository: SakuraByteCore/codexmate
Length of output: 881
🏁 Script executed:
Repository: SakuraByteCore/codexmate
Length of output: 50
🏁 Script executed:
Repository: SakuraByteCore/codexmate
Length of output: 3748
🏁 Script executed:
Repository: SakuraByteCore/codexmate
Length of output: 50
Clarify the impact of increased message loading and pagination strategy.
The
sessionDetailInitialMessageLimitwas set to 300 (vs. the runtimesessionDetailMessageLimitof 80), and combined with the auto-fetch recursion (lines 457-476 insession-helpers.mjs), a clipped session will trigger multiple fetches of 300 messages each (up to the 1000 cap). The template renders allactiveSessionMessagesat once without batching (line 265 inpanel-sessions.html), so a large session could accumulate 300→600→900→1000 messages in DOM at once.For sessions with large message payloads, this could cause:
activeSessionMessagesConsider whether the 300-message initial batch is justified by your typical session sizes, or if starting smaller (e.g., 100-150) with larger fetch steps would be safer.
🤖 Prompt for AI Agents