diff --git a/src/main/mobile/lan-mobile-pages.ts b/src/main/mobile/lan-mobile-pages.ts index 0af91c042..cbd22b093 100644 --- a/src/main/mobile/lan-mobile-pages.ts +++ b/src/main/mobile/lan-mobile-pages.ts @@ -126,13 +126,13 @@ function renderMessage(message){const blocks=message.blocks.filter(Boolean);retu function presetIsLocked(){return!sessionBlank||optimisticPrompts.length>0} function closeSessionSettings(){$('sessionSettings').hidden=true;$('sessionSettings').innerHTML='';$('settings').setAttribute('aria-expanded','false')} function selectedModelEntry(){const value=$('modelSelect')?.value||'',parts=value.split('\u001f'),group=(modelCatalog?.groups||[]).find(item=>item.id===parts[0]);return{group,model:group?.models?.find(item=>item.id===parts[1])}} - function syncEffortOptions(){const field=$('effortField'),select=$('effortSelect'),entry=selectedModelEntry().model,efforts=entry?.reasoning?.efforts||[];if(!field||!select)return;field.hidden=!efforts.length;if(!efforts.length){select.innerHTML='';return}const previous=select.value,current=modelCatalog?.current?.reasoningEffort,preferred=efforts.some(item=>item.id===previous)?previous:efforts.some(item=>item.id===current)?current:entry.reasoning.defaultEffort||efforts[0].id;select.innerHTML=efforts.map(item=>'').join('');select.value=preferred} - function syncSettingsControls(){const locked=presetIsLocked(),preset=$('presetSelect'),note=$('presetNote');if(preset)preset.disabled=settingsBusy||locked;if(note)note.textContent=locked?L.presetLocked:L.presetEditable;const model=$('modelSelect'),effort=$('effortSelect');if(model)model.disabled=settingsBusy||!modelCatalog?.routable;if(effort)effort.disabled=settingsBusy||!modelCatalog?.routable} - function renderSessionSettings(){const host=$('sessionSettings');if(!modelCatalog){host.innerHTML='
'+L.sessionSettings+'
'+L.settingsLoading+'
';return}const current=modelCatalog.current||{},modelValue=current.provider+'\u001f'+current.model,presetFallback=presets.find(item=>item.isDefault)?.id||presets[0]?.id||'',presetValue=presets.some(item=>item.id===currentPreset)?currentPreset:presetFallback;host.innerHTML='
'+L.sessionSettings+'
'+(!modelCatalog.groups?.length?L.noModels:'')+'
';if((modelCatalog.groups||[]).some(group=>(group.models||[]).some(model=>group.id+'\u001f'+model.id===modelValue)))$('modelSelect').value=modelValue;if($('presetSelect'))$('presetSelect').value=presetValue;syncEffortOptions();syncSettingsControls()} + function syncEffortOptions(){const field=$('effortField'),select=$('effortSelect'),entry=selectedModelEntry().model,efforts=entry?.reasoning?.efforts||[];if(!field||!select)return;field.hidden=!efforts.length;if(!efforts.length){select.innerHTML='';return}const previous=select.value,current=(modelCatalog?.current??modelCatalog?.default)?.reasoningEffort,preferred=efforts.some(item=>item.id===previous)?previous:efforts.some(item=>item.id===current)?current:entry.reasoning.defaultEffort||efforts[0].id;select.innerHTML=efforts.map(item=>'').join('');select.value=preferred} + function syncSettingsControls(){const locked=presetIsLocked(),preset=$('presetSelect'),note=$('presetNote');if(preset)preset.disabled=settingsBusy||locked;if(note)note.textContent=locked?L.presetLocked:L.presetEditable;const model=$('modelSelect'),effort=$('effortSelect'),routable=(modelCatalog?.routableProviders?.length??0)>0||modelCatalog?.routable===true;if(model)model.disabled=settingsBusy||!routable;if(effort)effort.disabled=settingsBusy||!routable} + function renderSessionSettings(){const host=$('sessionSettings');if(!modelCatalog){host.innerHTML='
'+L.sessionSettings+'
'+L.settingsLoading+'
';return}const current=modelCatalog.current??modelCatalog.default??{},modelValue=current.provider+'\u001f'+current.model,presetFallback=presets.find(item=>item.isDefault)?.id||presets[0]?.id||'',presetValue=presets.some(item=>item.id===currentPreset)?currentPreset:presetFallback;host.innerHTML='
'+L.sessionSettings+'
'+(!modelCatalog.groups?.length?L.noModels:'')+'
';if((modelCatalog.groups||[]).some(group=>(group.models||[]).some(model=>group.id+'\u001f'+model.id===modelValue)))$('modelSelect').value=modelValue;if($('presetSelect'))$('presetSelect').value=presetValue;syncEffortOptions();syncSettingsControls()} async function refreshActiveSessionSummary(){if(!activeSession)return;const value=await rpc('session.list',{}),summary=(value.items||[]).find(item=>item.sessionId===activeSession);if(summary){sessionBlank=summary.blank;currentPreset=summary.agentPreset||currentPreset;sessionSummaries=value.items||[]}syncSettingsControls()} - async function openSessionSettings(){if(!$('sessionSettings').hidden){closeSessionSettings();return}const sessionId=activeSession;if(!sessionId)return;$('sessionSettings').hidden=false;$('settings').setAttribute('aria-expanded','true');modelCatalog=null;renderSessionSettings();try{const [models,presetValue,sessions]=await Promise.all([rpc('session.models',{sessionId}),rpc('agentPreset.list',{}),rpc('session.list',{})]);if(activeSession!==sessionId)return;modelCatalog=models;presets=(presetValue.presets||[]).filter(preset=>!preset.broken);sessionSummaries=sessions.items||[];const summary=sessionSummaries.find(item=>item.sessionId===sessionId);if(summary){sessionBlank=summary.blank;currentPreset=summary.agentPreset||currentPreset}renderSessionSettings()}catch(e){if(activeSession!==sessionId)return;modelCatalog={current:{provider:'',model:''},routable:false,groups:[],failures:[]};renderSessionSettings();showError('settingsError',e)}} + async function openSessionSettings(){if(!$('sessionSettings').hidden){closeSessionSettings();return}const sessionId=activeSession;if(!sessionId)return;$('sessionSettings').hidden=false;$('settings').setAttribute('aria-expanded','true');modelCatalog=null;renderSessionSettings();try{const [models,presetValue,sessions]=await Promise.all([rpc('session.models',{sessionId}),rpc('agentPreset.list',{}),rpc('session.list',{})]);if(activeSession!==sessionId)return;modelCatalog=models;presets=(presetValue.presets||[]).filter(preset=>!preset.broken);sessionSummaries=sessions.items||[];const summary=sessionSummaries.find(item=>item.sessionId===sessionId);if(summary){sessionBlank=summary.blank;currentPreset=summary.agentPreset||currentPreset}renderSessionSettings()}catch(e){if(activeSession!==sessionId)return;modelCatalog={default:{provider:'',model:''},routableProviders:[],groups:[],failures:[]};renderSessionSettings();showError('settingsError',e)}} async function selectPreset(){const select=$('presetSelect');if(!select||settingsBusy||presetIsLocked()||!activeSession)return;const previous=currentPreset,next=select.value;if(!next||next===previous)return;settingsBusy=true;syncSettingsControls();try{const value=await rpc('agentPreset.select',{sessionId:activeSession,agentPreset:next});currentPreset=value.agentPreset;showToast(L.settingsUpdated)}catch(e){select.value=previous||select.value;showError('settingsError',e);await refreshActiveSessionSummary().catch(()=>{})}finally{settingsBusy=false;syncSettingsControls()}} - async function selectModel(){const select=$('modelSelect');if(!select||settingsBusy||!activeSession)return;const entry=selectedModelEntry(),provider=entry.group?.id,model=entry.model?.id;if(!provider||!model)return;settingsBusy=true;syncSettingsControls();const reasoningEffort=$('effortSelect')?.value||entry.model?.reasoning?.defaultEffort;try{const value=await rpc('session.selectModel',{sessionId:activeSession,provider,model,...(reasoningEffort?{reasoningEffort}:{})});modelCatalog.current=value.selected;renderSessionSettings();showToast(L.settingsUpdated)}catch(e){showError('settingsError',e);syncSettingsControls()}finally{settingsBusy=false;syncSettingsControls()}} + async function selectModel(){const select=$('modelSelect');if(!select||settingsBusy||!activeSession)return;const entry=selectedModelEntry(),provider=entry.group?.id,model=entry.model?.id;if(!provider||!model)return;settingsBusy=true;syncSettingsControls();const reasoningEffort=$('effortSelect')?.value||entry.model?.reasoning?.defaultEffort;try{const value=await rpc('session.selectModel',{sessionId:activeSession,provider,model,...(reasoningEffort?{reasoningEffort}:{})});modelCatalog.current=modelCatalog.default=value.selected;renderSessionSettings();showToast(L.settingsUpdated)}catch(e){showError('settingsError',e);syncSettingsControls()}finally{settingsBusy=false;syncSettingsControls()}} function durableUserTextCounts(messages){const counts=new Map();for(const message of messages){if(message.role!=='user')continue;const text=message.blocks?.filter(block=>block?.kind==='text').map(block=>block.text).join('\\n')||'';counts.set(text,(counts.get(text)||0)+1)}return counts} function messagesWithOptimistic(durable){const counts=durableUserTextCounts(durable);optimisticPrompts=optimisticPrompts.filter(item=>(counts.get(item.text)||0)({role:'user',blocks:[{kind:'text',text:item.text}],optimistic:true}))]} function nextOptimisticTarget(text){let target=latestUserTextCounts.get(text)||0;for(const item of optimisticPrompts)if(item.text===text)target=Math.max(target,item.targetCount);return target+1}