opencode-navigator 0.18.2 → 0.19.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/tui.js CHANGED
@@ -1,8 +1,9 @@
1
- import {insert as _$insert,setProp as _$setProp,createElement as _$createElement,createComponent as _$createComponent,mergeProps as _$mergeProps,effect as _$effect,createTextNode as _$createTextNode,insertNode as _$insertNode,memo as _$memo,use as _$use,spread as _$spread,useTerminalDimensions,useTerminalDimensions as useTerminalDimensions2,useTerminalDimensions as useTerminalDimensions3,useTerminalDimensions as useTerminalDimensions4,useTerminalDimensions as useTerminalDimensions5,useTerminalDimensions as useTerminalDimensions6,useTerminalDimensions as useTerminalDimensions7} from "@opentui/solid"
1
+ import {insert as _$insert,setProp as _$setProp,createElement as _$createElement,memo as _$memo,createComponent as _$createComponent,mergeProps as _$mergeProps,effect as _$effect,createTextNode as _$createTextNode,insertNode as _$insertNode,use as _$use,spread as _$spread,useTerminalDimensions,useTerminalDimensions as useTerminalDimensions2,useTerminalDimensions as useTerminalDimensions3,useTerminalDimensions as useTerminalDimensions4,useTerminalDimensions as useTerminalDimensions5,useTerminalDimensions as useTerminalDimensions6,useTerminalDimensions as useTerminalDimensions7} from "@opentui/solid"
2
2
 
3
3
 
4
4
 
5
- import {createSignal as createSignal2,createSignal,createEffect,onCleanup,createContext,useContext,createContext as createContext2,createSignal as createSignal3,useContext as useContext2,createEffect as createEffect2,splitProps,untrack,splitProps as splitProps2,For,createEffect as createEffect3,onCleanup as onCleanup2,Show,splitProps as splitProps3,createSignal as createSignal4,createSignal as createSignal5,createSignal as createSignal6,onCleanup as onCleanup3,batch,createSignal as createSignal8,createSignal as createSignal7,createEffect as createEffect4,createSignal as createSignal9,onCleanup as onCleanup4,createSignal as createSignal10,createSignal as createSignal11,Index,createSignal as createSignal12,onCleanup as onCleanup5,createEffect as createEffect6,onCleanup as onCleanup7,batch as batch2,createEffect as createEffect5,createMemo,createSignal as createSignal13,onCleanup as onCleanup6,onMount,For as For2,For as For3,Show as Show2,createMemo as createMemo2,Show as Show3,createSignal as createSignal14,onCleanup as onCleanup8,For as For4,For as For5,For as For8,createMemo as createMemo4,onMount as onMount3,For as For7,createMemo as createMemo3,onMount as onMount2,Show as Show5,createEffect as createEffect7,createSignal as createSignal15,onCleanup as onCleanup9,Show as Show4,For as For6,For as For9,createEffect as createEffect8,createMemo as createMemo5,onCleanup as onCleanup10,For as For10,createEffect as createEffect9,createMemo as createMemo8,onCleanup as onCleanup11,onMount as onMount4,createMemo as createMemo6,createMemo as createMemo7,Show as Show6,onCleanup as onCleanup12,createSignal as createSignal16,createEffect as createEffect10,onCleanup as onCleanup13,onMount as onMount5,onCleanup as onCleanup14,onMount as onMount6,For as For11,createSignal as createSignal17,createSignal as createSignal18,Show as Show7,createSignal as createSignal20,createSignal as createSignal19,onCleanup as onCleanup15,For as For12,Show as Show10,createMemo as createMemo10,createComputed,createMemo as createMemo9,createSignal as createSignal21,untrack as untrack2,Show as Show8,createComputed as createComputed2,untrack as untrack3,Show as Show9,createEffect as createEffect11,createSignal as createSignal22,createMemo as createMemo12,createSignal as createSignal24,createMemo as createMemo11,For as For13,Show as Show13,Show as Show11,Show as Show12,createSignal as createSignal23,onCleanup as onCleanup16,For as For14,Show as Show15,createMemo as createMemo14,Show as Show14,createMemo as createMemo13,createSignal as createSignal25,createEffect as createEffect12,onCleanup as onCleanup17,For as For19,Match,Switch,createMemo as createMemo18,onCleanup as onCleanup21,For as For15,Show as Show16,createSignal as createSignal26,createEffect as createEffect13,createMemo as createMemo15,onCleanup as onCleanup18,untrack as untrack4,For as For17,Show as Show19,createEffect as createEffect14,createMemo as createMemo16,createSignal as createSignal27,onCleanup as onCleanup19,untrack as untrack5,For as For16,Show as Show18,Show as Show17,Show as Show23,createEffect as createEffect15,createMemo as createMemo17,createSignal as createSignal28,onCleanup as onCleanup20,untrack as untrack6,For as For18,Show as Show21,Show as Show20,Show as Show22,createEffect as createEffect16,createMemo as createMemo19,onCleanup as onCleanup22,untrack as untrack7,Show as Show24,createMemo as createMemo20,onCleanup as onCleanup23,createSignal as createSignal29,onCleanup as onCleanup24,onMount as onMount7} from "solid-js"
5
+
6
+ import {createSignal as createSignal2,createSignal,createEffect,onCleanup,createContext,useContext,createContext as createContext2,createSignal as createSignal3,useContext as useContext2,createEffect as createEffect2,splitProps,untrack,splitProps as splitProps2,For,createEffect as createEffect3,onCleanup as onCleanup2,Show,splitProps as splitProps3,createSignal as createSignal4,createSignal as createSignal5,createSignal as createSignal6,onCleanup as onCleanup3,batch,createSignal as createSignal8,createSignal as createSignal7,createEffect as createEffect4,createSignal as createSignal9,onCleanup as onCleanup4,createSignal as createSignal10,createSignal as createSignal11,Index,createSignal as createSignal12,onCleanup as onCleanup5,createEffect as createEffect6,onCleanup as onCleanup7,batch as batch2,createEffect as createEffect5,createMemo,createSignal as createSignal13,onCleanup as onCleanup6,onMount,For as For2,For as For3,Show as Show2,createMemo as createMemo2,Show as Show3,createSignal as createSignal14,onCleanup as onCleanup8,For as For4,For as For5,For as For8,createMemo as createMemo4,onMount as onMount3,For as For7,createMemo as createMemo3,onMount as onMount2,Show as Show5,createEffect as createEffect7,createSignal as createSignal15,onCleanup as onCleanup9,Show as Show4,For as For6,For as For9,createEffect as createEffect8,createMemo as createMemo5,onCleanup as onCleanup10,createEffect as createEffect9,createMemo as createMemo6,untrack as untrack2,For as For10,createEffect as createEffect10,createMemo as createMemo9,onCleanup as onCleanup11,onMount as onMount4,createMemo as createMemo7,createMemo as createMemo8,Show as Show6,onCleanup as onCleanup12,createEffect as createEffect11,onCleanup as onCleanup13,createSignal as createSignal16,createEffect as createEffect12,onCleanup as onCleanup14,onMount as onMount5,onCleanup as onCleanup15,onMount as onMount6,For as For11,createSignal as createSignal17,createSignal as createSignal18,Show as Show7,createSignal as createSignal20,createSignal as createSignal19,onCleanup as onCleanup16,For as For12,Show as Show10,createMemo as createMemo11,createComputed,createMemo as createMemo10,createSignal as createSignal21,untrack as untrack3,Show as Show8,createComputed as createComputed2,untrack as untrack4,Show as Show9,createEffect as createEffect13,createSignal as createSignal22,createMemo as createMemo13,createSignal as createSignal24,createMemo as createMemo12,For as For13,Show as Show14,Show as Show11,Show as Show12,Show as Show13,createSignal as createSignal23,onCleanup as onCleanup17,For as For14,Show as Show16,createMemo as createMemo15,Show as Show15,createMemo as createMemo14,createSignal as createSignal25,createEffect as createEffect14,onCleanup as onCleanup18,For as For19,Match,Switch,createMemo as createMemo19,onCleanup as onCleanup22,For as For15,Show as Show17,createSignal as createSignal26,createEffect as createEffect15,createMemo as createMemo16,onCleanup as onCleanup19,untrack as untrack5,For as For17,Show as Show20,createEffect as createEffect16,createMemo as createMemo17,createSignal as createSignal27,onCleanup as onCleanup20,untrack as untrack6,For as For16,Show as Show19,Show as Show18,Show as Show24,createEffect as createEffect17,createMemo as createMemo18,createSignal as createSignal28,onCleanup as onCleanup21,untrack as untrack7,For as For18,Show as Show22,Show as Show21,Show as Show23,createEffect as createEffect18,createMemo as createMemo20,onCleanup as onCleanup23,untrack as untrack8,Show as Show25,createMemo as createMemo21,onCleanup as onCleanup24,createSignal as createSignal29,onCleanup as onCleanup25,onMount as onMount7} from "solid-js"
6
7
  var SIDEBAR_SECTIONS=["todo","subagents","skills","quick_actions","lsp","mcp"]
7
8
  var QUICK_ACTION_IDS=["session.rename","session.timeline","session.copy","session.export","session.compact","session.list","session.new","session.fork","messages.copy","session.first","session.last","session.messages_last_user","session.message.next","session.message.previous","permission.mode"]
8
9
  function preferencesScope(path){return path.worktree||path.directory||"global"
@@ -189,6 +190,23 @@ function mcpToggleAction2(status){if(status==="pending")
189
190
  return
190
191
  return status==="connected"?"disconnect":"connect"
191
192
  }
193
+ var BUCKET_RANK={Favorites:0,Ungrouped:2}
194
+ function mcpGroupToggleAction(items){if(items.some((item)=>mcpToggleAction2(item.status)==="connect"))
195
+ return "connect"
196
+ return items.some((item)=>mcpToggleAction2(item.status)==="disconnect")?"disconnect":undefined
197
+ }
198
+ function buildMcpGroupedView(items,favorites,assignments){return items.map((item)=>({...item,assignedGroup:assignments[item.name],bucket:favorites.has(item.name)?"Favorites":assignments[item.name]??"Ungrouped"
199
+ })).sort((left,right)=>{const leftRank=BUCKET_RANK[left.bucket]??1
200
+ const rightRank=BUCKET_RANK[right.bucket]??1
201
+ return leftRank-rightRank||left.bucket.localeCompare(right.bucket)||left.name.localeCompare(right.name)
202
+ })
203
+ }
204
+ function bulkDescription(operation,action){if(operation.action==="preset")
205
+ return `apply ${operation.preset} MCP preset`
206
+ if(operation.group)
207
+ return `${action} ${operation.group} MCP group`
208
+ return `${action} all MCP servers`
209
+ }
192
210
  function matchingMcpPreset(items,presets){if(items.length===0)
193
211
  return
194
212
  return Object.keys(presets).sort((left,right)=>left.localeCompare(right)).find((name)=>{const states=presets[name]
@@ -377,8 +395,7 @@ const failed=[]
377
395
  const retry=[]
378
396
  await Promise.all(changes.map(async ({name,action})=>{if(operation.action!=="preset")
379
397
  save(current,name,action==="disconnect")
380
- try{const description=operation.action==="preset"?`apply ${operation.preset} MCP preset`:`${action} all MCP servers`
381
- await changeServer(current,name,action,description,false)
398
+ try{await changeServer(current,name,action,bulkDescription(operation,action),false)
382
399
  } catch(error){if(!isAbortError(error)){failed.push(name)
383
400
  retry.push({name,action})
384
401
  }} finally{setBulkStates((values)=>{if(bulkGenerations.get(current.key)!==generation)
@@ -396,7 +413,9 @@ await refresh(current,true).catch(()=>{})
396
413
  failed.sort((left,right)=>left.localeCompare(right))
397
414
  setBulkStates((values)=>({...values,[current.key]:{...operation,status:failed.length>0?"error":"ready",completed:changes.length,total:changes.length,failed
398
415
  }}))
399
- if(failed.length>0&&activeTarget===current.key){const action=operation.action==="preset"?`apply ${operation.preset}`:operation.action
416
+ if(failed.length>0&&activeTarget===current.key){let action=operation.action==="preset"?`apply ${operation.preset}`:operation.action
417
+ if(operation.group)
418
+ action += ` ${operation.group}`
400
419
  api.ui.toast({variant:"warning",title:"MCP servers",message:`Could not ${action}: ${failed.join(", ")}`,duration:4000
401
420
  })
402
421
  }}
@@ -445,19 +464,25 @@ return changeMany({action:"connect"},list(current).filter((item)=>mcpToggleActio
445
464
  return
446
465
  resetSelectedPreset(current)
447
466
  return changeMany({action:"disconnect"},list(current).filter((item)=>mcpToggleAction2(item.status)==="disconnect").map((item)=>({name:item.name,action:"disconnect"})),current)
467
+ },toggleGroup(group,names,current=target()){if(target().key!==current.key||mutating(current)||bulkState(current).status==="running")
468
+ return
469
+ const selected=new Set(names)
470
+ const items=list(current).filter((item)=>selected.has(item.name))
471
+ const action=mcpGroupToggleAction(items)
472
+ if(!action)
473
+ return
474
+ resetSelectedPreset(current)
475
+ if(action==="connect"){for(const item of items)
476
+ if(item.status==="connected")
477
+ save(current,item.name,false)
478
+ }
479
+ return changeMany({action,group},items.filter((item)=>mcpToggleAction2(item.status)===action).map((item)=>({name:item.name,action})),current)
448
480
  },retryBulk(current=target()){const state=bulkState(current)
449
481
  if(state.status!=="error"||state.failed.length===0)
450
482
  return
451
483
  const changes=bulkRetries.get(current.key)??[]
452
- return changeMany({action:state.action,...state.preset&&{preset:state.preset}},changes,current)
484
+ return changeMany({action:state.action,...state.preset&&{preset:state.preset},...state.group&&{group:state.group}},changes,current)
453
485
  }}}
454
- var BUCKET_RANK={Favorites:0,Ungrouped:2}
455
- function buildMcpGroupedView(items,favorites,assignments){return items.map((item)=>({...item,assignedGroup:assignments[item.name],bucket:favorites.has(item.name)?"Favorites":assignments[item.name]??"Ungrouped"
456
- })).sort((left,right)=>{const leftRank=BUCKET_RANK[left.bucket]??1
457
- const rightRank=BUCKET_RANK[right.bucket]??1
458
- return leftRank-rightRank||left.bucket.localeCompare(right.bucket)||left.name.localeCompare(right.name)
459
- })
460
- }
461
486
 
462
487
 
463
488
 
@@ -1036,6 +1061,17 @@ function McpErrorDialog(props){return _$createComponent(PresetMenu,{get api(){re
1036
1061
  },onSelect:()=>{}})
1037
1062
  }
1038
1063
 
1064
+ function assignGroup(groups,key,value){const next={...groups}
1065
+ if(!key)
1066
+ return next
1067
+ const group=value?.trim().slice(0,64)
1068
+ if(!group){delete next[key]
1069
+ return next
1070
+ }
1071
+ const canonical=Object.values(next).find((item)=>item.toLocaleLowerCase()===group.toLocaleLowerCase())
1072
+ next[key]=canonical??group
1073
+ return next
1074
+ }
1039
1075
  var PORTABLE_SETTINGS_FORMAT="opencode-navigator/settings"
1040
1076
  function object(value,path){if(!value||typeof value!=="object"||Array.isArray(value))
1041
1077
  throw new Error(`${path} must be an object`)
@@ -1178,6 +1214,7 @@ return Object.fromEntries(Object.entries(input).flatMap(([server,rawGroup])=>{co
1178
1214
  return server.trim()&&group?[[server,group]]:[]
1179
1215
  }))
1180
1216
  }
1217
+ var parseSkillGroups=parseMcpServerGroups
1181
1218
  function parseWorkspaceProfiles(value){return Object.fromEntries(Object.entries(record(value)??{}).flatMap(([layout,rawMcp])=>{const layoutName=layout.trim().slice(0,64)
1182
1219
  const mcpName=typeof rawMcp==="string"?rawMcp.trim().slice(0,64):""
1183
1220
  return layoutName&&mcpName?[[layoutName,mcpName]]:[]
@@ -1211,11 +1248,13 @@ const favoriteQuickActions=parseFavoriteQuickActions(userInput?.favoriteQuickAct
1211
1248
  const recentSkills=parseRecentSkills(userInput?.recentSkills)
1212
1249
  const recentQuickActions=parseRecentQuickActions(userInput?.recentQuickActions)
1213
1250
  const mcpServerGroups=parseMcpServerGroups(userInput?.mcpServerGroups)
1251
+ const skillGroups=parseSkillGroups(userInput?.skillGroups)
1214
1252
  const workspaceProfiles=parseWorkspaceProfiles(userInput?.workspaceProfiles)
1215
1253
  return{global:{...Object.keys(behavior).length>0&&{behavior},...layout&&{layout},...Object.keys(globalMcp).length>0&&{mcp:globalMcp}},worktrees,user:{...skippedSkillConfirmations&&{skippedSkillConfirmations},...typeof userInput?.onboardingCompleted==="boolean"&&{onboardingCompleted:userInput.onboardingCompleted
1216
1254
  },...typeof userInput?.lastNavigatorVersion==="string"&&{lastNavigatorVersion:userInput.lastNavigatorVersion
1217
1255
  },...typeof userInput?.previousNavigatorVersion==="string"&&{previousNavigatorVersion:userInput.previousNavigatorVersion
1218
- },...Object.keys(layoutPresets).length>0&&{layoutPresets},...Object.keys(mcpPresets).length>0&&{mcpPresets},...favoriteSkills&&{favoriteSkills},...favoriteMcpServers?.length&&{favoriteMcpServers},...favoriteQuickActions.length>0&&{favoriteQuickActions},...recentSkills.length>0&&{recentSkills},...recentQuickActions.length>0&&{recentQuickActions},...Object.keys(mcpServerGroups).length>0&&{mcpServerGroups},...Object.keys(workspaceProfiles).length>0&&{workspaceProfiles}}}}
1256
+ },...Object.keys(layoutPresets).length>0&&{layoutPresets},...Object.keys(mcpPresets).length>0&&{mcpPresets},...favoriteSkills&&{favoriteSkills},...favoriteMcpServers?.length&&{favoriteMcpServers},...favoriteQuickActions.length>0&&{favoriteQuickActions},...recentSkills.length>0&&{recentSkills},...recentQuickActions.length>0&&{recentQuickActions},...Object.keys(mcpServerGroups).length>0&&{mcpServerGroups},...Object.keys(skillGroups).length>0&&{skillGroups},...typeof userInput?.autoApprovePermissions==="boolean"&&{autoApprovePermissions:userInput.autoApprovePermissions
1257
+ },...Object.keys(workspaceProfiles).length>0&&{workspaceProfiles}}}}
1219
1258
  function parseValues(value){if(!value)
1220
1259
  return{}
1221
1260
  return{behavior:parsePluginSettings(value.behavior),layout:{sections:parseSectionPreferences(value.layout?.sections),expanded:parseSectionPreferences(value.layout?.expanded),...parseSectionOrder(value.layout?.order)&&{order:parseSectionOrder(value.layout?.order)}},desiredMcpStates:parseDesiredMcpStates(value.desiredMcpStates)
@@ -1360,14 +1399,8 @@ favoriteQuickActions.delete(quickActionFavorite.id)
1360
1399
  }
1361
1400
  const recentSkills=parseRecentSkills([...update.user?.recentSkill?[update.user.recentSkill]:[],...current.user.recentSkills??[]])
1362
1401
  const recentQuickActions=parseRecentQuickActions([...update.user?.recentQuickAction?[update.user.recentQuickAction]:[],...current.user.recentQuickActions??[]])
1363
- const mcpServerGroups={...current.user.mcpServerGroups}
1364
- const groupUpdate=update.user?.mcpServerGroup
1365
- if(groupUpdate?.name){const group=groupUpdate.group?.trim().slice(0,64)
1366
- if(group){const canonical=Object.values(mcpServerGroups).find((value)=>value.toLocaleLowerCase()===group.toLocaleLowerCase())
1367
- mcpServerGroups[groupUpdate.name]=canonical??group
1368
- } else
1369
- delete mcpServerGroups[groupUpdate.name]
1370
- }
1402
+ const mcpServerGroups=assignGroup(current.user.mcpServerGroups,update.user?.mcpServerGroup?.name,update.user?.mcpServerGroup?.group)
1403
+ const skillGroups=assignGroup(current.user.skillGroups,update.user?.skillGroup?.location,update.user?.skillGroup?.group)
1371
1404
  const favoriteSkills=update.user?.favoriteSkills?parseSkillConfirmations(update.user.favoriteSkills):[...current.user.favoriteSkills??[]]
1372
1405
  const favoriteSkill=update.user?.favoriteSkill
1373
1406
  if(favoriteSkill?.location){const index=favoriteSkills.indexOf(favoriteSkill.location)
@@ -1383,7 +1416,8 @@ return{global:target.kind==="global"?scope:current.global,worktrees,user:{...ski
1383
1416
  },...(update.user?.previousNavigatorVersion??current.user.previousNavigatorVersion)&&{previousNavigatorVersion:update.user?.previousNavigatorVersion??current.user.previousNavigatorVersion
1384
1417
  },...Object.keys(parsedLayoutPresets).length>0&&{layoutPresets:parsedLayoutPresets},...Object.keys(parsedMcpPresets).length>0&&{mcpPresets:parsedMcpPresets},...Object.keys(workspaceProfiles).length>0&&{workspaceProfiles:parseWorkspaceProfiles(workspaceProfiles)
1385
1418
  },...favoriteSkills.length>0&&{favoriteSkills},...favoriteMcpServers.size>0&&{favoriteMcpServers:[...favoriteMcpServers].sort()},...favoriteQuickActions.size>0&&{favoriteQuickActions:parseFavoriteQuickActions([...favoriteQuickActions])
1386
- },...recentSkills.length>0&&{recentSkills},...recentQuickActions.length>0&&{recentQuickActions},...Object.keys(mcpServerGroups).length>0&&{mcpServerGroups:parseMcpServerGroups(mcpServerGroups)}}}}
1419
+ },...recentSkills.length>0&&{recentSkills},...recentQuickActions.length>0&&{recentQuickActions},...Object.keys(mcpServerGroups).length>0&&{mcpServerGroups:parseMcpServerGroups(mcpServerGroups)},...Object.keys(skillGroups).length>0&&{skillGroups:parseSkillGroups(skillGroups)},...typeof (update.user?.autoApprovePermissions??current.user.autoApprovePermissions)==="boolean"&&{autoApprovePermissions:update.user?.autoApprovePermissions??current.user.autoApprovePermissions
1420
+ }}}}
1387
1421
  function targetForLegacyScope(scope){return scope==="global"?{kind:"global"}:{kind:"worktree",key:scope}}
1388
1422
  function createPreferencesStore(stateDirectory){const directory=join(stateDirectory,LEGACY_PLUGIN_ID)
1389
1423
  const file=join(directory,"preferences.json")
@@ -1551,6 +1585,8 @@ const [favoriteQuickActions,setFavoriteQuickActions]=createSignal4(new Set)
1551
1585
  const [recentSkills,setRecentSkills]=createSignal4([])
1552
1586
  const [recentQuickActions,setRecentQuickActions]=createSignal4([])
1553
1587
  const [mcpServerGroups,setMcpServerGroups]=createSignal4(configured.mcpServerGroups??{})
1588
+ const [skillGroups,setSkillGroups]=createSignal4({})
1589
+ const [autoApprovePermissions,setAutoApprovePermissions]=createSignal4()
1554
1590
  const [ready,setReady]=createSignal4(false)
1555
1591
  const [revision,setRevision]=createSignal4(0)
1556
1592
  const sessionLayouts=new Map
@@ -1560,6 +1596,8 @@ let isHydrated=false
1560
1596
  let hydration
1561
1597
  let mcpPresetRevision=0
1562
1598
  let mcpPresetReconciliation=Promise.resolve()
1599
+ let updateRevision=0
1600
+ let reloading
1563
1601
  let isPersistenceWarningShown=false
1564
1602
  function skillKey(skill){return skill.location
1565
1603
  }
@@ -1597,13 +1635,30 @@ return{...configured.workspaceProfiles,...document.user.workspaceProfiles}}
1597
1635
  function scopeSnapshot(target=selectedTarget()){const scope=target.kind==="global"?document.global:document.worktrees[target.key]
1598
1636
  return JSON.stringify({layout:scope?.layout,mcp:scope?.mcp})
1599
1637
  }
1600
- function update(change){document=applyPreferencesUpdate(document,change)
1638
+ function update(change){updateRevision++
1639
+ document=applyPreferencesUpdate(document,change)
1601
1640
  if(isHydrated)
1602
1641
  persist(store.update(change))
1603
1642
  else
1604
1643
  pendingUpdates.push(change)
1605
1644
  refreshResolved()
1606
1645
  }
1646
+ function applyDocument(value){document=value
1647
+ setSkippedSkills(new Set(value.user.skippedSkillConfirmations))
1648
+ setOnboardingCompleted(value.user.onboardingCompleted===true)
1649
+ setLayoutPresets({...configured.layoutPresets,...value.user.layoutPresets})
1650
+ setMcpPresets({...configured.mcpPresets,...value.user.mcpPresets})
1651
+ setFavoriteSkills(new Set(value.user.favoriteSkills))
1652
+ setFavoriteMcpServers(new Set(value.user.favoriteMcpServers))
1653
+ setFavoriteQuickActions(new Set(value.user.favoriteQuickActions))
1654
+ setRecentSkills(value.user.recentSkills??[])
1655
+ setRecentQuickActions(value.user.recentQuickActions??[])
1656
+ setMcpServerGroups({...configured.mcpServerGroups,...value.user.mcpServerGroups})
1657
+ setSkillGroups(value.user.skillGroups??{})
1658
+ setAutoApprovePermissions(value.user.autoApprovePermissions)
1659
+ setReady(true)
1660
+ refreshResolved()
1661
+ }
1607
1662
  function load(){if(isHydrated)
1608
1663
  return Promise.resolve()
1609
1664
  if(hydration)
@@ -1618,21 +1673,28 @@ const queued=[...pendingUpdates]
1618
1673
  pendingUpdates.length=0
1619
1674
  for(const change of queued)
1620
1675
  persist(store.update(change))
1621
- setSkippedSkills(new Set(document.user.skippedSkillConfirmations))
1622
- setOnboardingCompleted(document.user.onboardingCompleted===true)
1623
- setLayoutPresets({...configured.layoutPresets,...document.user.layoutPresets})
1624
- setMcpPresets({...configured.mcpPresets,...document.user.mcpPresets})
1625
- setFavoriteSkills(new Set(document.user.favoriteSkills))
1626
- setFavoriteMcpServers(new Set(document.user.favoriteMcpServers))
1627
- setFavoriteQuickActions(new Set(document.user.favoriteQuickActions))
1628
- setRecentSkills(document.user.recentSkills??[])
1629
- setRecentQuickActions(document.user.recentQuickActions??[])
1630
- setMcpServerGroups({...configured.mcpServerGroups,...document.user.mcpServerGroups})
1631
- setReady(true)
1632
- refreshResolved()
1676
+ applyDocument(document)
1633
1677
  })
1634
1678
  return hydration
1635
1679
  }
1680
+ async function reloadFromFile(){if(reloading)
1681
+ return reloading
1682
+ const request=(async ()=>{await load()
1683
+ while(true){const observedRevision=updateRevision
1684
+ await store.flush()
1685
+ await mcpPresetReconciliation
1686
+ const latest=await store.load()
1687
+ if(observedRevision!==updateRevision)
1688
+ continue
1689
+ sessionLayouts.clear()
1690
+ applyDocument(latest)
1691
+ return
1692
+ }})()
1693
+ reloading=request
1694
+ try{await request
1695
+ } finally{if(reloading===request)
1696
+ reloading=undefined
1697
+ }}
1636
1698
  function setKey(value,name){load()
1637
1699
  const next=value.trim()
1638
1700
  if(!validKey(next))
@@ -1698,6 +1760,22 @@ next.add(key)
1698
1760
  setFavoriteSkills(next)
1699
1761
  update({user:{favoriteSkill:{location:key,favorite:next.has(key)}}})
1700
1762
  }
1763
+ function changeSkillGroup(location,value){if(!location)
1764
+ return
1765
+ if(!isHydrated){load().then(()=>changeSkillGroup(location,value))
1766
+ return
1767
+ }
1768
+ setSkillGroups(assignGroup(skillGroups(),location,value))
1769
+ update({user:{skillGroup:{location,group:value}}})
1770
+ }
1771
+ function changeAutoApprovePermissions(value){if(!isHydrated){load().then(()=>changeAutoApprovePermissions(value))
1772
+ return
1773
+ }
1774
+ if(autoApprovePermissions()===value)
1775
+ return
1776
+ setAutoApprovePermissions(value)
1777
+ update({user:{autoApprovePermissions:value}})
1778
+ }
1701
1779
  function toggleFavoriteMcpServer(name){if(!isHydrated){load().then(()=>toggleFavoriteMcpServer(name))
1702
1780
  return
1703
1781
  }
@@ -1755,6 +1833,7 @@ const target=selectedTarget()
1755
1833
  if(preview.target!==targetKey(target))
1756
1834
  throw new Error("Preference scope changed; reopen the import preview")
1757
1835
  const change={target,expectedScope:preview.expectedScope,...preview.settings.layout&&{layout:preview.settings.layout,clearLayout:true},...preview.settings.mcp&&{mcp:{states:preview.settings.mcp},clearMcp:true}}
1836
+ updateRevision++
1758
1837
  await store.update(change)
1759
1838
  document=await store.load()
1760
1839
  sessionLayouts.delete(targetKey(target))
@@ -1765,15 +1844,9 @@ throw new Error("Layout preset no longer exists")
1765
1844
  if(mcp&&!mcpPresets()[mcp])
1766
1845
  throw new Error("MCP preset no longer exists")
1767
1846
  update({user:{workspaceProfile:{layout,mcp}}})
1768
- },favoriteSkills,favoriteMcpServers,favoriteQuickActions,toggleFavoriteMcpServer,toggleFavoriteQuickAction,recentSkills,recentQuickActions,mcpServerGroups,setMcpServerGroup(name,value){const group=value?.trim().slice(0,64)
1769
- const next={...mcpServerGroups()}
1770
- if(group){const canonical=Object.values(next).find((item)=>item.toLocaleLowerCase()===group.toLocaleLowerCase())
1771
- next[name]=canonical??group
1772
- } else
1773
- delete next[name]
1774
- setMcpServerGroups(next)
1775
- update({user:{mcpServerGroup:{name,group}}})
1776
- },async recordSkillUse(skill){await load()
1847
+ },favoriteSkills,favoriteMcpServers,favoriteQuickActions,toggleFavoriteMcpServer,toggleFavoriteQuickAction,recentSkills,recentQuickActions,mcpServerGroups,setMcpServerGroup(name,value){setMcpServerGroups(assignGroup(mcpServerGroups(),name,value))
1848
+ update({user:{mcpServerGroup:{name,group:value}}})
1849
+ },skillGroups,setSkillGroup:changeSkillGroup,autoApprovePermissions,setAutoApprovePermissions:changeAutoApprovePermissions,async recordSkillUse(skill){await load()
1777
1850
  if(!skill.location)
1778
1851
  return
1779
1852
  setRecentSkills(parseRecentSkills([skill.location,...recentSkills()]))
@@ -1795,7 +1868,7 @@ setRevision((value)=>value + 1)
1795
1868
  },async flush(){await hydration
1796
1869
  await store.flush()
1797
1870
  await mcpPresetReconciliation
1798
- },async claimNavigatorUpgrade(version){await load()
1871
+ },reloadFromFile,async claimNavigatorUpgrade(version){await load()
1799
1872
  const previous=document.user.lastNavigatorVersion
1800
1873
  if(previous===version)
1801
1874
  return
@@ -1904,6 +1977,7 @@ return true
1904
1977
  },async saveLayoutAsDefault(){await load()
1905
1978
  const target=selectedTarget()
1906
1979
  const layout=resolveTarget(target).layout
1980
+ updateRevision++
1907
1981
  document=applyPreferencesUpdate(document,{target,layout})
1908
1982
  await store.update({target,layout})
1909
1983
  refreshResolved()
@@ -2063,6 +2137,12 @@ return result.data
2063
2137
  throw error_
2064
2138
  } finally{request.finish()
2065
2139
  }}}}
2140
+ var BUCKET_RANK2={Favorites:0,Ungrouped:2}
2141
+ function buildSkillGroupedView(items,favorites,groups,recent){return items.map((item)=>({...item,assignedGroup:groups[item.location],bucket:favorites.has(item.location)?"Favorites":groups[item.location]??"Ungrouped"
2142
+ })).sort((left,right)=>{const rank=(BUCKET_RANK2[left.bucket]??1)-(BUCKET_RANK2[right.bucket]??1)
2143
+ return rank||left.bucket.localeCompare(right.bucket)||(left.bucket==="Favorites"?0:(recent.get(left.location)??Infinity)-(recent.get(right.location)??Infinity))||left.name.localeCompare(right.name)
2144
+ })
2145
+ }
2066
2146
 
2067
2147
 
2068
2148
 
@@ -2738,7 +2818,7 @@ return{groups,rows:groups.flatMap((group)=>group.items.map((item)=>({item,group:
2738
2818
 
2739
2819
  function KeyboardHelpDialog(props){const icons=useIcons()
2740
2820
  const theme=()=>props.api.theme.current
2741
- const hints=()=>[`${icons.key("up")}/k and ${icons.key("down")}/j move \xB7 ${icons.key("enter")} activates`,`${icons.key("enter")} on a filter starts typing \xB7 ${icons.key("esc")} returns`,`Todo: ${icons.key("enter")} on All / Active / Finished changes the view`,"Show all / Show less expands or limits the filtered list",`Skills: ${icons.icon("info")} opens source \xB7 ${icons.icon("recent")} marks recent skills`,"Navigator Settings: Ctrl+,",`Search Everything: shortcut in Settings ${icons.icon("right")} Behavior`,`Search: type \xB7 ${icons.key("up/down")} results \xB7 ${icons.key("tab/shift+tab")} tabs \xB7 ${icons.key("enter")} run`,`${icons.key("esc")} leaves the sidebar \xB7 ${icons.key("?")} opens this help`]
2821
+ const hints=()=>[`${icons.key("up")}/k and ${icons.key("down")}/j move \xB7 ${icons.key("enter")} activates`,`${icons.key("enter")} on a filter starts typing \xB7 ${icons.key("esc")} returns`,`Todo: ${icons.key("enter")} on All / Active / Finished changes the view`,`MCP: ${icons.key("enter")} toggles a group`,"Show all / Show less expands or limits the filtered list",`Skills: ${icons.icon("info")} opens source \xB7 ${icons.icon("recent")} marks recent skills`,"Navigator Settings: Ctrl+,",`Search Everything: shortcut in Settings ${icons.icon("right")} Behavior`,`Search: type \xB7 ${icons.key("up/down")} results \xB7 ${icons.key("tab/shift+tab")} tabs \xB7 ${icons.key("enter")} run`,`${icons.key("esc")} leaves the sidebar \xB7 ${icons.key("?")} opens this help`]
2742
2822
  return _$createComponent(DialogSurface,{get api(){return props.api
2743
2823
  },get children(){return [(()=>{var _el$=_$createElement("text"),_el$2=_$createTextNode(` Navigator keyboard help`)
2744
2824
  _$insertNode(_el$,_el$2)
@@ -2806,7 +2886,7 @@ return{sessionID,location,key:JSON.stringify([route.name,sessionID??null,locatio
2806
2886
  function buildSearchCandidates(input){const recent=new Map(input.recentSkills.map((location,index)=>[location,index]))
2807
2887
  const skills=[...input.skills].sort((a,b)=>Number(input.favoriteSkills.has(b.location))-Number(input.favoriteSkills.has(a.location))||(recent.get(a.location)??Infinity)-(recent.get(b.location)??Infinity)||a.name.localeCompare(b.name))
2808
2888
  const mcp=[...input.mcp].sort((a,b)=>Number(input.favoriteMcp.has(b.name))-Number(input.favoriteMcp.has(a.name))||a.name.localeCompare(b.name))
2809
- const results=[...skills.map((skill)=>({id:`skill:${skill.location || skill.name}`,group:"Skills",title:skill.name,description:skill.description?.trim()||skill.location,keywords:skill.location,skill
2889
+ const results=[...skills.map((skill)=>({id:`skill:${skill.location || skill.name}`,group:"Skills",title:skill.name,description:[input.skillGroups?.[skill.location],skill.description?.trim()||skill.location].filter(Boolean).join(" \xB7 "),keywords:`${skill.location} ${input.skillGroups?.[skill.location] ?? ""}`,skill
2810
2890
  })),...input.subagents.map((item)=>({id:`subagent:${item.session.id}`,group:"Subagents",title:item.session.title,description:[item.run?.outcome??item.status.type,item.run?.errorMessage].filter(Boolean).join(" \xB7 "),keywords:item.session.id,sessionID:item.session.id
2811
2891
  })),...mcp.map((item)=>({id:`mcp:${item.name}`,group:"MCP",title:item.name,description:[input.mcpGroups?.[item.name],mcpToggleAction2(item.status)==="disconnect"?"Disconnect":"Connect",item.status,item.error].filter(Boolean).join(" \xB7 "),keywords:input.mcpGroups?.[item.name],disabled:input.mcpBusy||!mcpToggleAction2(item.status)?"MCP operation in progress":undefined,server:item.name
2812
2892
  })),...orderQuickActionIds(input.actionOrder,input.favoriteQuickActions??new Set).flatMap((id)=>{const action=QUICK_ACTIONS.find((item)=>item.command===id)
@@ -2889,7 +2969,7 @@ let isDisposed=false
2889
2969
  let refreshGeneration=0
2890
2970
  const sameContext=()=>searchContext(props.api).key===context.key
2891
2971
  const candidates=createMemo(()=>{commandRevision()
2892
- return buildSearchCandidates({skills:props.skills.list(skillTarget),subagents:context.sessionID?buildSubagentView(props.subagents.list(context.sessionID),props.subagents.recent(context.sessionID)):[],mcp:props.mcp.list(mcpTarget),actionOrder:props.preferences.quickActionOrder?.()??QUICK_ACTION_IDS,favoriteQuickActions:props.preferences.favoriteQuickActions?.()??new Set,favoriteSkills:props.preferences.favoriteSkills(),recentSkills:props.preferences.recentSkills(),favoriteMcp:props.preferences.favoriteMcpServers(),mcpGroups:props.preferences.mcpServerGroups?.()??{},hasSession:Boolean(context.sessionID),mcpBusy:props.mcp.mutating(mcpTarget)||props.mcp.bulkState(mcpTarget).status==="running",actionDisabledReason:(action)=>quickActionDisabledReason(props.api,action),actionLabel:(action)=>quickActionLabel(props.api,action)
2972
+ return buildSearchCandidates({skills:props.skills.list(skillTarget),subagents:context.sessionID?buildSubagentView(props.subagents.list(context.sessionID),props.subagents.recent(context.sessionID)):[],mcp:props.mcp.list(mcpTarget),actionOrder:props.preferences.quickActionOrder?.()??QUICK_ACTION_IDS,favoriteQuickActions:props.preferences.favoriteQuickActions?.()??new Set,favoriteSkills:props.preferences.favoriteSkills(),skillGroups:props.preferences.skillGroups?.()??{},recentSkills:props.preferences.recentSkills(),favoriteMcp:props.preferences.favoriteMcpServers(),mcpGroups:props.preferences.mcpServerGroups?.()??{},hasSession:Boolean(context.sessionID),mcpBusy:props.mcp.mutating(mcpTarget)||props.mcp.bulkState(mcpTarget).status==="running",actionDisabledReason:(action)=>quickActionDisabledReason(props.api,action),actionLabel:(action)=>quickActionLabel(props.api,action)
2893
2973
  })
2894
2974
  })
2895
2975
  const matches=createMemo(()=>searchResults(candidates(),query()))
@@ -3319,6 +3399,8 @@ return section!=="todo"&&section!=="lsp"?true:current[section]
3319
3399
  }
3320
3400
  function supportsTitleVisibility(api){return hostCapabilities(api).titleVisibility!==false
3321
3401
  }
3402
+ function supportsPermissionMode(api){return hostCapabilities(api).permissionMode!==false
3403
+ }
3322
3404
  var ONBOARDING_STEPS=[{title:"A control center that stays compact",summary:"Navigator brings session state, search, and controls into OpenCode's existing sidebar.",icon:"help",features:[{icon:"sections",title:"Progressive disclosure",description:"Expand only the context you need right now."},{icon:"scope",title:"Current context",description:"Follow the active session, workspace, and worktree."},{icon:"actions",title:"Mouse and keyboard",description:"Use the same controls with either input method."}]
3323
3405
  },{title:"Stay oriented while agents work",summary:"Keep current work visible without turning the sidebar into another dashboard.",icon:"todo",features:[{icon:"todo",title:"Todo filters",description:"Separate active, finished, and cancelled work."},{icon:"subagents",title:"Live subagents",description:"See running, retrying, recent, and failed child sessions."
3324
3406
  },{icon:"history",title:"Direct navigation",description:"Open a child session without leaving your workflow."
@@ -3942,42 +4024,7 @@ reportMcpApplyError(props.api,request)
3942
4024
  }
3943
4025
 
3944
4026
 
3945
- function McpGroupAssignmentDialog(props){const dialogs=useDialogs(props.api)
3946
- const options=()=>{const assigned=props.preferences.mcpServerGroups?.()[props.server]
3947
- const groups=[...new Set(Object.values(props.preferences.mcpServerGroups?.()??{}))].sort((a,b)=>a.localeCompare(b))
3948
- return [...groups.map((group)=>({title:group,value:`:${group}`,description:group===assigned?"Current":"Existing group"
3949
- })),{title:"Create new group",value:"+",description:"Type a name"
3950
- },{title:"Ungrouped",value:":",description:assigned?"Remove assignment":"No group"
3951
- }]
3952
- }
3953
- return _$createComponent(PresetMenu,{get api(){return props.api
3954
- },get title(){return `Group for ${props.server}`
3955
- },get options(){return options()
3956
- },onSelect:(option)=>{if(option.value!=="+"){props.preferences.setMcpServerGroup?.(props.server,option.value.slice(1)||undefined)
3957
- dialogs.back()
3958
- return
3959
- }
3960
- dialogs.prompt({title:`New group for ${props.server}`,value:"",onConfirm(value){if(!value.trim())
3961
- throw new Error("Group name is required")
3962
- props.preferences.setMcpServerGroup?.(props.server,value)
3963
- dialogs.back()
3964
- dialogs.back()
3965
- }})
3966
- }})
3967
- }
3968
- function McpGroupsDialog(props){const dialogs=useDialogs(props.api)
3969
- const options=()=>{const live=new Set(props.mcp.list(props.mcp.target()).map((item)=>item.name))
3970
- return [...new Set([...live,...Object.keys(props.preferences.mcpServerGroups?.()??{})])].sort((a,b)=>a.localeCompare(b)).map((name)=>({title:name,value:name,description:[props.preferences.mcpServerGroups?.()[name]??"Ungrouped",!live.has(name)&&"not in workspace"].filter(Boolean).join(" \xB7 ")
3971
- }))
3972
- }
3973
- return _$createComponent(PresetMenu,{get api(){return props.api
3974
- },title:"MCP groups \xB7 user-wide",get options(){return options()
3975
- },onSelect:(option)=>dialogs.open(()=>_$createComponent(McpGroupAssignmentDialog,{get api(){return props.api
3976
- },get preferences(){return props.preferences
3977
- },get server(){return option.value
3978
- }}))
3979
- })
3980
- }
4027
+
3981
4028
 
3982
4029
 
3983
4030
 
@@ -4054,139 +4101,8 @@ dialogs.open(()=>_$createComponent(PresetMenu,{api,title:"MCP presets",get optio
4054
4101
 
4055
4102
 
4056
4103
 
4057
- function QuickActionsDialog(props){const order=props.preferences.selectedQuickActionOrder
4058
- const dialogs=useDialogs(props.api)
4059
- const scroll=useDialogScroll()
4060
- const [selected,setSelected]=useDialogState("selection",order()[0])
4061
- const actions=createMemo5(()=>order().map((id)=>({...QUICK_ACTIONS.find((action)=>action.command===id)
4062
- })))
4063
- const theme=()=>props.api.theme.current
4064
- const icons=useIcons()
4065
- const dimensions=useTerminalDimensions5()
4066
- let body
4067
- function move(offset){const index=order().indexOf(selected())
4068
- setSelected(order()[(index + offset + order().length)%order().length])
4069
- }
4070
- const prefix=`${PLUGIN_ID}.quick-actions-settings`
4071
- createEffect8(()=>{order()
4072
- const id=selected()
4073
- queueMicrotask(()=>{if(body&&!body.isDestroyed)
4074
- body.scrollChildIntoView(`${prefix}.${id}`)
4075
- })
4076
- })
4077
- const unregister=props.api.keymap.registerLayer({mode:"modal",priority:1000,commands:[{name:`${prefix}.previous`,run:()=>move(-1)
4078
- },{name:`${prefix}.next`,run:()=>move(1)
4079
- },{name:`${prefix}.toggle`,run:()=>props.preferences.toggleQuickAction(selected())
4080
- },{name:`${prefix}.up`,run:()=>props.preferences.moveQuickAction(selected(),-1)
4081
- },{name:`${prefix}.down`,run:()=>props.preferences.moveQuickAction(selected(),1)
4082
- },{name:`${prefix}.back`,run:dialogs.back
4083
- }],bindings:[{key:"up",cmd:`${prefix}.previous`
4084
- },{key:"down",cmd:`${prefix}.next`
4085
- },{key:"return",cmd:`${prefix}.toggle`
4086
- },{key:"space",cmd:`${prefix}.toggle`
4087
- },{key:"left",cmd:`${prefix}.up`
4088
- },{key:"right",cmd:`${prefix}.down`
4089
- },{key:"shift+up",cmd:`${prefix}.up`
4090
- },{key:"shift+down",cmd:`${prefix}.down`
4091
- },{key:"escape",cmd:`${prefix}.back`
4092
- }]
4093
- })
4094
- onCleanup10(unregister)
4095
- return _$createComponent(DialogSurface,{get api(){return props.api
4096
- },id:prefix,lift:true,get children(){return [(()=>{var _el$=_$createElement("box"),_el$2=_$createElement("text"),_el$3=_$createTextNode(` Quick actions`),_el$4=_$createElement("text"),_el$5=_$createTextNode(` Back (`),_el$6=_$createTextNode(`)`)
4097
- _$insertNode(_el$,_el$2)
4098
- _$insertNode(_el$,_el$4)
4099
- _$setProp(_el$,"flexDirection","row")
4100
- _$setProp(_el$,"justifyContent","space-between")
4101
- _$insertNode(_el$2,_el$3)
4102
- _$insert(_el$2,()=>icons.icon("actions"),_el$3)
4103
- _$insertNode(_el$4,_el$5)
4104
- _$insertNode(_el$4,_el$6)
4105
- _$setProp(_el$4,"onMouseUp",(event)=>{event.stopPropagation()
4106
- dialogs.back()
4107
- })
4108
- _$insert(_el$4,()=>icons.icon("left"),_el$5)
4109
- _$insert(_el$4,()=>icons.key("esc"),_el$6)
4110
- _$effect((_p$)=>{var _v$=TextAttributes14.BOLD,_v$2=theme().text,_v$3=theme().textMuted
4111
- _v$!==_p$.e&&(_p$.e=_$setProp(_el$2,"attributes",_v$,_p$.e))
4112
- _v$2!==_p$.t&&(_p$.t=_$setProp(_el$2,"fg",_v$2,_p$.t))
4113
- _v$3!==_p$.a&&(_p$.a=_$setProp(_el$4,"fg",_v$3,_p$.a))
4114
- return _p$
4115
- },{e:undefined,t:undefined,a:undefined
4116
- })
4117
- return _el$
4118
- })(),(()=>{var _el$7=_$createElement("text"),_el$8=_$createTextNode(`Scope: `),_el$9=_$createTextNode(`. Changes save immediately.`)
4119
- _$insertNode(_el$7,_el$8)
4120
- _$insertNode(_el$7,_el$9)
4121
- _$setProp(_el$7,"wrapMode","word")
4122
- _$insert(_el$7,()=>props.preferences.preferenceScopeLabel(),_el$9)
4123
- _$effect((_$p)=>_$setProp(_el$7,"fg",theme().textMuted,_$p))
4124
- return _el$7
4125
- })(),(()=>{var _el$0=_$createElement("scrollbox"),_el$1=_$createElement("box")
4126
- _$insertNode(_el$0,_el$1)
4127
- _$use((node)=>{body=node
4128
- scroll.ref(node)
4129
- },_el$0)
4130
- _$setProp(_el$0,"scrollX",false)
4131
- _$setProp(_el$1,"gap",1)
4132
- _$insert(_el$1,_$createComponent(For9,{get each(){return actions()
4133
- },children:(action,index)=>_$createComponent(SelectionBox,{get id(){return `${prefix}.${action.command}`
4134
- },flexDirection:"row",gap:1,paddingLeft:1,paddingRight:1,get backgroundColor(){return _$memo(()=>selected()===action.command)()?theme().backgroundElement:undefined
4135
- },onMouseOver:()=>setSelected(action.command),onMouseDown:()=>{setSelected(action.command)
4136
- props.preferences.toggleQuickAction(action.command)
4137
- },get children(){return [(()=>{var _el$16=_$createElement("text"),_el$17=_$createTextNode(` `),_el$18=_$createTextNode(`. `),_el$19=_$createTextNode(` `)
4138
- _$insertNode(_el$16,_el$17)
4139
- _$insertNode(_el$16,_el$18)
4140
- _$insertNode(_el$16,_el$19)
4141
- _$setProp(_el$16,"flexGrow",1)
4142
- _$insert(_el$16,()=>icons.icon(props.preferences.selectedQuickActionVisible(action.command)?"checked":"unchecked"),_el$17)
4143
- _$insert(_el$16,()=>index() + 1,_el$18)
4144
- _$insert(_el$16,()=>icons.action(action.command),_el$19)
4145
- _$insert(_el$16,()=>quickActionLabel(props.api,action),null)
4146
- _$effect((_$p)=>_$setProp(_el$16,"fg",theme().text,_$p))
4147
- return _el$16
4148
- })(),(()=>{var _el$20=_$createElement("text")
4149
- _$setProp(_el$20,"onMouseDown",(event)=>{event.stopPropagation()
4150
- setSelected(action.command)
4151
- props.preferences.moveQuickAction(action.command,-1)
4152
- })
4153
- _$insert(_el$20,()=>icons.icon("up"))
4154
- _$effect((_$p)=>_$setProp(_el$20,"fg",theme().accent,_$p))
4155
- return _el$20
4156
- })(),(()=>{var _el$21=_$createElement("text")
4157
- _$setProp(_el$21,"onMouseDown",(event)=>{event.stopPropagation()
4158
- setSelected(action.command)
4159
- props.preferences.moveQuickAction(action.command,1)
4160
- })
4161
- _$insert(_el$21,()=>icons.icon("down"))
4162
- _$effect((_$p)=>_$setProp(_el$21,"fg",theme().accent,_$p))
4163
- return _el$21
4164
- })()]
4165
- }})
4166
- }))
4167
- _$effect((_p$)=>{var{restore:_v$4,save:_v$5}=scroll,_v$6=Math.min(actions().length*2-1,Math.max(3,Math.floor(dimensions().height*0.75)-8))
4168
- _v$4!==_p$.e&&(_p$.e=_$setProp(_el$0,"renderBefore",_v$4,_p$.e))
4169
- _v$5!==_p$.t&&(_p$.t=_$setProp(_el$0,"renderAfter",_v$5,_p$.t))
4170
- _v$6!==_p$.a&&(_p$.a=_$setProp(_el$0,"height",_v$6,_p$.a))
4171
- return _p$
4172
- },{e:undefined,t:undefined,a:undefined
4173
- })
4174
- return _el$0
4175
- })(),(()=>{var _el$10=_$createElement("text"),_el$11=_$createTextNode(` navigate \xB7 `),_el$12=_$createTextNode(` toggle \xB7 `),_el$13=_$createTextNode(` or `),_el$15=_$createTextNode(` reorder`)
4176
- _$insertNode(_el$10,_el$11)
4177
- _$insertNode(_el$10,_el$12)
4178
- _$insertNode(_el$10,_el$13)
4179
- _$insertNode(_el$10,_el$15)
4180
- _$setProp(_el$10,"wrapMode","word")
4181
- _$insert(_el$10,()=>icons.key("up/down"),_el$11)
4182
- _$insert(_el$10,()=>icons.key("enter"),_el$12)
4183
- _$insert(_el$10,()=>icons.key("left/right"),_el$13)
4184
- _$insert(_el$10,()=>icons.key("shift+up/down"),_el$15)
4185
- _$effect((_$p)=>_$setProp(_el$10,"fg",theme().textMuted,_$p))
4186
- return _el$10
4187
- })()]
4188
- }})
4189
- }
4104
+
4105
+
4190
4106
 
4191
4107
 
4192
4108
 
@@ -4265,7 +4181,12 @@ return [{title:`${icons.icon(title ? "checked" : "unchecked")} Session title`,va
4265
4181
  }]
4266
4182
  }
4267
4183
  function createSettingsGroups(api,preferences,icons){const supportedSections=()=>SIDEBAR_SECTIONS.filter((name)=>supportsSidebarSection(api,name))
4268
- const groups=createMemo6(()=>[{id:"scope",tab:"Scope",title:"Preference scope",options:[{title:`${icons.icon(preferences.preferenceScope() === "global" ? "radioOn" : "radioOff")} Global`,value:"scope:global",description:"applies to every worktree"
4184
+ const permissionDefaultDescription=()=>{const value=preferences.autoApprovePermissions()
4185
+ if(value===undefined)
4186
+ return "follow OpenCode startup mode"
4187
+ return value?"on for new sessions":"off for new sessions"
4188
+ }
4189
+ const groups=createMemo7(()=>[{id:"scope",tab:"Scope",title:"Preference scope",options:[{title:`${icons.icon(preferences.preferenceScope() === "global" ? "radioOn" : "radioOff")} Global`,value:"scope:global",description:"applies to every worktree"
4269
4190
  },{title:`${icons.icon(preferences.preferenceScope() === "worktree" ? "radioOn" : "radioOff")} Current worktree`,value:"scope:worktree",description:preferences.canUseWorktreeScope()?preferences.preferenceScopeLabel():"unavailable outside a worktree"
4270
4191
  }]
4271
4192
  },{id:"presets",tab:"Presets",title:"Layout presets",options:[...Object.keys(preferences.layoutPresets()).sort((left,right)=>left.localeCompare(right)).map((name)=>({title:`${icons.icon("presets")} ${name}`,value:`preset:custom:${encodeURIComponent(name)}`,description:preferences.workspaceProfiles?.()[name]?`profile \xB7 ${preferences.workspaceProfiles()[name]}`:"enter to apply or edit"
@@ -4274,7 +4195,8 @@ const groups=createMemo6(()=>[{id:"scope",tab:"Scope",title:"Preference scope",o
4274
4195
  },{id:"sections",tab:"Sections",title:"Sections & order",options:[...titleVisibilityOptions(api,preferences,icons),...preferences.selectedSectionOrder().filter((name)=>supportsSidebarSection(api,name)).map((name,index)=>{const section=SECTION_DEFINITIONS.find((candidate)=>candidate.name===name)
4275
4196
  return{title:`${icons.icon(preferences.selectedSections()[section.name] ? "checked" : "unchecked")} ${index + 1}. ${icons.section(section.name)} ${section.label}`,value:section.name,description:preferences.selectedSections()[section.name]?"visible":"hidden"
4276
4197
  }})]
4277
- },{id:"behavior",tab:"Behavior",title:"Behavior",options:[{title:`${icons.icon(preferences.selectedStartInChat() ? "checked" : "unchecked")} Start new sessions in chat`,value:"start_in_chat",description:preferences.selectedStartInChat()?"skip Home \xB7 on":"show Home \xB7 off"
4198
+ },{id:"behavior",tab:"Behavior",title:"Behavior",options:[...supportsPermissionMode(api)?[{title:`${icons.icon(preferences.autoApprovePermissions() === true ? "checked" : "unchecked")} Default auto-approve permissions`,value:"auto_approve_permissions",description:permissionDefaultDescription()
4199
+ }]:[],{title:`${icons.icon(preferences.selectedStartInChat() ? "checked" : "unchecked")} Start new sessions in chat`,value:"start_in_chat",description:preferences.selectedStartInChat()?"skip Home \xB7 on":"show Home \xB7 off"
4278
4200
  },{title:`${icons.icon(preferences.selectedPersistMcp() ? "checked" : "unchecked")} Remember MCP states`,value:"persist_mcp",description:preferences.selectedPersistMcp()?"on":"off"
4279
4201
  },{title:`${icons.icon("settings")} Icon style`,value:"lsp_icon_style",description:preferences.selectedLspIconStyle()==="nerd"?"Nerd Font":"Text fallback"
4280
4202
  },{title:`${icons.icon(preferences.selectedCornerFont() ? "checked" : "unchecked")} Multiline corner font`,value:"corner_font",description:preferences.selectedCornerFont()?"Installed":"Not installed \xB7 rectangular highlights"
@@ -4286,6 +4208,7 @@ return{title:`${icons.icon(preferences.selectedSections()[section.name] ? "check
4286
4208
  },{id:"defaults",tab:"Defaults",title:"Defaults & help",options:[{title:`${icons.icon("save")} Save current layout as default`,value:"save_layout",description:`${supportedSections().filter((name) => preferences.selectedSections()[name]).length} visible \xB7 ${supportedSections().filter((name) => preferences.selectedExpanded()[name]).length} expanded`
4287
4209
  },{title:`${icons.icon("export")} Copy portable settings`,value:"export_settings",description:"versioned layout and MCP JSON"
4288
4210
  },{title:`${icons.icon("add")} Import portable settings\u2026`,value:"import_settings",description:"preview pasted JSON before applying"
4211
+ },{title:`${icons.icon("retry")} Reload settings from file`,value:"reload_settings",description:"sync saved changes from other OpenCode sessions"
4289
4212
  },{title:`${icons.icon("reset")} Restore configured layout`,value:"reset_sections",description:"visibility and expansion"
4290
4213
  },{title:`${icons.icon("reset")} Restore configured behavior`,value:"reset_settings",description:"startup, MCP memory, icons, shortcuts, limits, actions"
4291
4214
  },{title:`${icons.icon("reset")} Clear remembered MCP states`,value:"reset_mcp",description:`scope: ${preferences.preferenceScopeLabel()}`
@@ -4293,17 +4216,21 @@ return{title:`${icons.icon(preferences.selectedSections()[section.name] ? "check
4293
4216
  },{title:`${icons.icon("help")} Open quick setup guide`,value:"wizard",description:"tips and section settings"
4294
4217
  }]
4295
4218
  }])
4296
- const orderedGroups=createMemo6(()=>["sections","scope","presets","behavior","defaults"].map((id)=>groups().find((group)=>group.id===id)))
4219
+ const orderedGroups=createMemo7(()=>["sections","scope","presets","behavior","defaults"].map((id)=>groups().find((group)=>group.id===id)))
4297
4220
  return orderedGroups
4298
4221
  }
4299
- function registerSettingsKeymap(input){return input.api.keymap.registerLayer({mode:"modal",priority:1000,commands:[{name:`${PLUGIN_ID}.settings.previous`,run:()=>input.move(-1)},{name:`${PLUGIN_ID}.settings.next`,run:()=>input.move(1)},{name:`${PLUGIN_ID}.settings.select`,run:()=>input.select()},{name:`${PLUGIN_ID}.settings.mcp-groups`,run:()=>{if(input.activeGroup()==="sections"&&input.options()[input.active()]?.value==="mcp")
4222
+ function registerSettingsKeymap(input){return input.api.keymap.registerLayer({mode:"modal",priority:1000,commands:[{name:`${PLUGIN_ID}.settings.previous`,run:()=>input.move(-1)},{name:`${PLUGIN_ID}.settings.next`,run:()=>input.move(1)},{name:`${PLUGIN_ID}.settings.select`,run:()=>input.select()},{name:`${PLUGIN_ID}.settings.groups`,run:()=>{if(input.activeGroup()!=="sections")
4223
+ return
4224
+ if(input.options()[input.active()]?.value==="mcp")
4300
4225
  input.openMcpGroups()
4226
+ if(input.options()[input.active()]?.value==="skills")
4227
+ input.openSkillGroups()
4301
4228
  }},{name:`${PLUGIN_ID}.settings.quick-actions`,run:()=>{if(input.activeGroup()==="sections"&&input.options()[input.active()]?.value==="quick_actions")
4302
4229
  input.openQuickActions()
4303
4230
  }},{name:`${PLUGIN_ID}.settings.item-limit`,run:()=>{const section=input.options()[input.active()]?.value
4304
4231
  if(input.activeGroup()==="sections"&&SIDEBAR_SECTIONS.includes(section))
4305
4232
  input.openLimitPrompt(section)
4306
- }},{name:`${PLUGIN_ID}.settings.previous-tab`,run:()=>input.switchGroup(-1)},{name:`${PLUGIN_ID}.settings.next-tab`,run:()=>input.switchGroup(1)},{name:`${PLUGIN_ID}.settings.move-up`,run:()=>input.reorder(input.options()[input.active()]?.value,-1)},{name:`${PLUGIN_ID}.settings.move-down`,run:()=>input.reorder(input.options()[input.active()]?.value,1)}],bindings:[{key:"up",cmd:`${PLUGIN_ID}.settings.previous`},{key:"down",cmd:`${PLUGIN_ID}.settings.next`},{key:"tab",cmd:`${PLUGIN_ID}.settings.next-tab`},{key:"shift+tab",cmd:`${PLUGIN_ID}.settings.previous-tab`},{key:"space",cmd:`${PLUGIN_ID}.settings.select`},{key:"return",cmd:`${PLUGIN_ID}.settings.select`},{key:"l",cmd:`${PLUGIN_ID}.settings.item-limit`},{key:"a",cmd:`${PLUGIN_ID}.settings.quick-actions`},{key:"g",cmd:`${PLUGIN_ID}.settings.mcp-groups`},{key:"left",cmd:`${PLUGIN_ID}.settings.move-up`},{key:"right",cmd:`${PLUGIN_ID}.settings.move-down`},{key:"shift+up",cmd:`${PLUGIN_ID}.settings.move-up`},{key:"shift+down",cmd:`${PLUGIN_ID}.settings.move-down`}]
4233
+ }},{name:`${PLUGIN_ID}.settings.previous-tab`,run:()=>input.switchGroup(-1)},{name:`${PLUGIN_ID}.settings.next-tab`,run:()=>input.switchGroup(1)},{name:`${PLUGIN_ID}.settings.move-up`,run:()=>input.reorder(input.options()[input.active()]?.value,-1)},{name:`${PLUGIN_ID}.settings.move-down`,run:()=>input.reorder(input.options()[input.active()]?.value,1)}],bindings:[{key:"up",cmd:`${PLUGIN_ID}.settings.previous`},{key:"down",cmd:`${PLUGIN_ID}.settings.next`},{key:"tab",cmd:`${PLUGIN_ID}.settings.next-tab`},{key:"shift+tab",cmd:`${PLUGIN_ID}.settings.previous-tab`},{key:"space",cmd:`${PLUGIN_ID}.settings.select`},{key:"return",cmd:`${PLUGIN_ID}.settings.select`},{key:"l",cmd:`${PLUGIN_ID}.settings.item-limit`},{key:"a",cmd:`${PLUGIN_ID}.settings.quick-actions`},{key:"g",cmd:`${PLUGIN_ID}.settings.groups`},{key:"left",cmd:`${PLUGIN_ID}.settings.move-up`},{key:"right",cmd:`${PLUGIN_ID}.settings.move-down`},{key:"shift+up",cmd:`${PLUGIN_ID}.settings.move-up`},{key:"shift+down",cmd:`${PLUGIN_ID}.settings.move-down`}]
4307
4234
  })
4308
4235
  }
4309
4236
 
@@ -4315,7 +4242,7 @@ input.openLimitPrompt(section)
4315
4242
 
4316
4243
 
4317
4244
  var RESET_ALL="__reset_all__"
4318
- function TrustedSkillsDialog(props){const options=createMemo7(()=>{const locations=props.preferences.trustedSkillLocations()
4245
+ function TrustedSkillsDialog(props){const options=createMemo8(()=>{const locations=props.preferences.trustedSkillLocations()
4319
4246
  if(locations.length===0)
4320
4247
  return [{title:"Every skill requires confirmation",value:"empty",description:"No trusted skills",icon:"info"
4321
4248
  }]
@@ -4331,7 +4258,8 @@ else if(option.value!=="empty")
4331
4258
  props.preferences.revokeSkillConfirmation(option.value)
4332
4259
  }})
4333
4260
  }
4334
- function createSettingsSelection(input){function openLimitPrompt(section){const index=input.options().findIndex((option)=>option.value===section)
4261
+ function createSettingsSelection(input){const dialogClosed=()=>("open" in input.api.ui.dialog)&&!input.api.ui.dialog.open
4262
+ function openLimitPrompt(section){const index=input.options().findIndex((option)=>option.value===section)
4335
4263
  if(index!==-1)
4336
4264
  input.setActive(index)
4337
4265
  input.dialogs.prompt({title:`${SECTION_DEFINITIONS.find((item) => item.name === section).label} item limit`,description:()=>(()=>{var _el$=_$createElement("text")
@@ -4418,6 +4346,11 @@ break
4418
4346
  case "import_settings":{importSettings()
4419
4347
  break
4420
4348
  }
4349
+ case "reload_settings":{input.preferences.reloadFromFile().then(()=>input.api.ui.toast({variant:"success",title:"Navigator settings",message:"Saved settings reloaded",duration:3000
4350
+ })).catch((error)=>input.api.ui.toast({variant:"error",title:"Navigator settings",message:error instanceof Error?error.message:"Could not reload saved settings",duration:5000
4351
+ }))
4352
+ break
4353
+ }
4421
4354
  case "reset_sections":{input.preferences.resetSections()
4422
4355
  break
4423
4356
  }
@@ -4433,6 +4366,9 @@ break
4433
4366
  case "start_in_chat":{input.preferences.toggleStartInChat()
4434
4367
  break
4435
4368
  }
4369
+ case "auto_approve_permissions":{input.preferences.setAutoApprovePermissions(input.preferences.autoApprovePermissions()!==true)
4370
+ break
4371
+ }
4436
4372
  case "lsp_icon_style":{input.preferences.toggleLspIconStyle()
4437
4373
  break
4438
4374
  }
@@ -4470,19 +4406,51 @@ break
4470
4406
  default:{input.preferences.toggleSelectedSection(value)
4471
4407
  }}}
4472
4408
  function openQuickActions(){input.setActive(input.options().findIndex((option)=>option.value==="quick_actions"))
4409
+ const path=import.meta.url.includes("/dist/tui.js")?"./quick-actions-settings.js":"../ui/quick-actions-dialog"
4410
+ import(path).then((module)=>{if(dialogClosed())
4411
+ return
4412
+ const{QuickActionsDialog
4413
+ }=module
4473
4414
  input.dialogs.open(()=>_$createComponent(QuickActionsDialog,{get api(){return input.api
4474
4415
  },get preferences(){return input.preferences
4475
4416
  }}))
4417
+ }).catch((error)=>{input.api.ui.toast({variant:"error",title:"Quick actions",message:String(error),duration:4000
4418
+ })
4419
+ })
4476
4420
  }
4477
4421
  function openMcpGroups(){if(!input.mcp)
4478
4422
  return
4479
4423
  input.setActive(input.options().findIndex((option)=>option.value==="mcp"))
4424
+ const path=import.meta.url.includes("/dist/tui.js")?"./mcp-groups.js":"../ui/mcp-groups-dialog"
4425
+ import(path).then((module)=>{if(dialogClosed())
4426
+ return
4427
+ const{McpGroupsDialog
4428
+ }=module
4480
4429
  input.dialogs.open(()=>_$createComponent(McpGroupsDialog,{get api(){return input.api
4481
4430
  },get preferences(){return input.preferences
4482
4431
  },get mcp(){return input.mcp
4483
4432
  }}))
4433
+ }).catch((error)=>{input.api.ui.toast({variant:"error",title:"MCP groups",message:String(error),duration:4000
4434
+ })
4435
+ })
4436
+ }
4437
+ function openSkillGroups(){if(!input.skills)
4438
+ return
4439
+ input.setActive(input.options().findIndex((option)=>option.value==="skills"))
4440
+ const path=import.meta.url.includes("/dist/tui.js")?"./skill-groups.js":"../ui/skill-groups-dialog"
4441
+ import(path).then((module)=>{if(dialogClosed())
4442
+ return
4443
+ const{SkillGroupsDialog
4444
+ }=module
4445
+ input.dialogs.open(()=>_$createComponent(SkillGroupsDialog,{get api(){return input.api
4446
+ },get preferences(){return input.preferences
4447
+ },get skills(){return input.skills
4448
+ }}))
4449
+ }).catch((error)=>{input.api.ui.toast({variant:"error",title:"Skill groups",message:String(error),duration:4000
4450
+ })
4451
+ })
4484
4452
  }
4485
- return{openLimitPrompt,openMcpGroups,openQuickActions,select
4453
+ return{openLimitPrompt,openMcpGroups,openSkillGroups,openQuickActions,select
4486
4454
  }}
4487
4455
  function createSettingsDialogController(props){let body
4488
4456
  const theme=()=>props.api.theme.current
@@ -4490,21 +4458,21 @@ const icons=useIcons()
4490
4458
  const dialogs=useDialogs(props.api)
4491
4459
  const scroll=useDialogScroll()
4492
4460
  const dimensions=useTerminalDimensions6()
4493
- const bodyHeight=createMemo8(()=>Math.max(4,Math.floor(dimensions().height*0.75)-10))
4461
+ const bodyHeight=createMemo9(()=>Math.max(4,Math.floor(dimensions().height*0.75)-10))
4494
4462
  const orderedGroups=createSettingsGroups(props.api,props.preferences,icons)
4495
4463
  const initialGroup=orderedGroups().find((group)=>group.options.some((option)=>option.value===props.activeValue))
4496
4464
  const [activeGroup,setActiveGroup]=useDialogState("tab",initialGroup?.id??orderedGroups()[0].id)
4497
- const options=createMemo8(()=>orderedGroups().find((group)=>group.id===activeGroup())?.options??[])
4465
+ const options=createMemo9(()=>orderedGroups().find((group)=>group.id===activeGroup())?.options??[])
4498
4466
  const optionId=(value)=>`${PLUGIN_ID}.settings.${value}`
4499
4467
  const initialActive=options().findIndex((option)=>option.value===props.activeValue)
4500
4468
  const [active,setActive]=useDialogState("selection",Math.max(0,initialActive))
4501
- createEffect9(()=>{if(active()>=options().length)
4469
+ createEffect10(()=>{if(active()>=options().length)
4502
4470
  setActive(Math.max(0,options().length-1))
4503
4471
  })
4504
- const contentHeight=createMemo8(()=>Math.min(bodyHeight(),Math.max(1,options().length*2-1)))
4505
- const footerHint=createMemo8(()=>{const common=`${icons.key("tab")} switch \xB7 ${icons.key("up/down")} navigate`
4472
+ const contentHeight=createMemo9(()=>Math.min(bodyHeight(),Math.max(1,options().length*2-1)))
4473
+ const footerHint=createMemo9(()=>{const common=`${icons.key("tab")} switch \xB7 ${icons.key("up/down")} navigate`
4506
4474
  if(activeGroup()==="sections")
4507
- return `${common} \xB7 ${icons.key("enter")} toggle \xB7 l item limit${options()[active()]?.value === "quick_actions" ? " \xB7 a actions" : ""}${options()[active()]?.value === "mcp" ? " \xB7 g groups" : ""} \xB7 ${icons.key("left/right")} or ${icons.key("shift+up/down")} reorder`
4475
+ return `${common} \xB7 ${icons.key("enter")} toggle \xB7 l item limit${options()[active()]?.value === "quick_actions" ? " \xB7 a actions" : ""}${["mcp", "skills"].includes(options()[active()]?.value ?? "") ? " \xB7 g groups" : ""} \xB7 ${icons.key("left/right")} or ${icons.key("shift+up/down")} reorder`
4508
4476
  if(activeGroup()==="presets")
4509
4477
  return `${common} \xB7 ${icons.key("enter")} manage`
4510
4478
  if(activeGroup()==="behavior")
@@ -4545,12 +4513,12 @@ body?.scrollChildIntoView(optionId(value))
4545
4513
  }
4546
4514
  const presetActions=createLayoutPresetActions({api:props.api,preferences:props.preferences,mcp:props.mcp,dialogs
4547
4515
  })
4548
- const selection=createSettingsSelection({api:props.api,preferences:props.preferences,mcp:props.mcp,dialogs,options,active,setActive,openPreset:presetActions.open,promptPreset:presetActions.prompt
4516
+ const selection=createSettingsSelection({api:props.api,preferences:props.preferences,mcp:props.mcp,skills:props.skills,dialogs,options,active,setActive,openPreset:presetActions.open,promptPreset:presetActions.prompt
4549
4517
  })
4550
- const unregister=registerSettingsKeymap({api:props.api,active,activeGroup,options,move,switchGroup,reorder,select:selection.select,openQuickActions:selection.openQuickActions,openMcpGroups:selection.openMcpGroups,openLimitPrompt:selection.openLimitPrompt
4518
+ const unregister=registerSettingsKeymap({api:props.api,active,activeGroup,options,move,switchGroup,reorder,select:selection.select,openQuickActions:selection.openQuickActions,openMcpGroups:selection.openMcpGroups,openSkillGroups:selection.openSkillGroups,openLimitPrompt:selection.openLimitPrompt
4551
4519
  })
4552
4520
  onCleanup11(unregister)
4553
- return{active,activeGroup,contentHeight,dialogs,footerHint,icons,openLimitPrompt:selection.openLimitPrompt,openQuickActions:selection.openQuickActions,openMcpGroups:selection.openMcpGroups,options,optionId,orderedGroups,reorder,select:selection.select,setActive,setActiveGroup,setBody(node){body=node
4521
+ return{active,activeGroup,contentHeight,dialogs,footerHint,icons,openLimitPrompt:selection.openLimitPrompt,openQuickActions:selection.openQuickActions,openMcpGroups:selection.openMcpGroups,openSkillGroups:selection.openSkillGroups,options,optionId,orderedGroups,reorder,select:selection.select,setActive,setActiveGroup,setBody(node){body=node
4554
4522
  scroll.ref(node)
4555
4523
  },restoreScroll:scroll.restore,saveScroll:scroll.save,theme
4556
4524
  }}
@@ -4606,11 +4574,14 @@ _$insert(_el$4,()=>model.icons.icon("actions"),_el$5)
4606
4574
  _$effect((_$p)=>_$setProp(_el$4,"fg",model.theme().accent,_$p))
4607
4575
  return _el$4
4608
4576
  }}),_el$8)
4609
- _$insert(_el$3,_$createComponent(Show6,{get when(){return props.option.value==="mcp"
4577
+ _$insert(_el$3,_$createComponent(Show6,{get when(){return props.option.value==="mcp"||props.option.value==="skills"
4610
4578
  },get children(){var _el$6=_$createElement("text"),_el$7=_$createTextNode(` Groups`)
4611
4579
  _$insertNode(_el$6,_el$7)
4612
4580
  _$setProp(_el$6,"onMouseDown",(event)=>event.stopPropagation())
4613
4581
  _$setProp(_el$6,"onMouseUp",(event)=>{event.stopPropagation()
4582
+ if(props.option.value==="skills")
4583
+ model.openSkillGroups()
4584
+ else
4614
4585
  model.openMcpGroups()
4615
4586
  })
4616
4587
  _$insert(_el$6,()=>model.icons.icon("sections"),_el$7)
@@ -4712,12 +4683,12 @@ return _el$0
4712
4683
  })()]
4713
4684
  }})
4714
4685
  }
4715
- function openSettings(api,preferences,activeValue,mcp){createDialogStack(api,preferences.lspIconStyle,()=>true,preferences.cornerFont).open(()=>_$createComponent(SettingsDialog,{api,preferences,mcp,activeValue
4686
+ function openSettings(api,preferences,activeValue,mcp,skills){createDialogStack(api,preferences.lspIconStyle,()=>true,preferences.cornerFont).open(()=>_$createComponent(SettingsDialog,{api,preferences,mcp,skills,activeValue
4716
4687
  }),"xlarge")
4717
4688
  }
4718
4689
 
4719
4690
 
4720
- function SettingsBinding(props){const unregister=props.api.keymap.registerLayer({mode:"base",commands:[{name:`${PLUGIN_ID}.settings`,title:"Navigator settings",category:"Navigator",namespace:"palette",enabled:()=>["home","session"].includes(props.api.route.current.name),run:()=>openSettings(props.api,props.preferences,undefined,props.mcp)
4691
+ function SettingsBinding(props){const unregister=props.api.keymap.registerLayer({mode:"base",commands:[{name:`${PLUGIN_ID}.settings`,title:"Navigator settings",category:"Navigator",namespace:"palette",enabled:()=>["home","session"].includes(props.api.route.current.name),run:()=>openSettings(props.api,props.preferences,undefined,props.mcp,props.skills)
4721
4692
  }],bindings:[{key:{name:",",ctrl:true
4722
4693
  },cmd:`${PLUGIN_ID}.settings`
4723
4694
  }]
@@ -4727,6 +4698,42 @@ return _$createElement("box")
4727
4698
  }
4728
4699
 
4729
4700
 
4701
+ function currentPermissionMode(api){const title=api.keymap.getCommands?.({visibility:"registered"
4702
+ }).find((command)=>command.name==="permission.mode")?.title
4703
+ if(typeof title!=="string")
4704
+ return
4705
+ if(title.startsWith("Disable auto-approve permissions"))
4706
+ return true
4707
+ return title.startsWith("Enable auto-approve permissions")?false:undefined
4708
+ }
4709
+ function PermissionModeBinding(props){let applying=false
4710
+ let observed
4711
+ createEffect11(()=>{if(!props.preferences.ready())
4712
+ return
4713
+ const preferred=props.preferences.autoApprovePermissions()
4714
+ const current=currentPermissionMode(props.api)
4715
+ observed=current
4716
+ if(preferred===undefined||current===undefined||current===preferred)
4717
+ return
4718
+ applying=true
4719
+ try{props.api.keymap.dispatchCommand("permission.mode")
4720
+ observed=currentPermissionMode(props.api)
4721
+ } finally{applying=false
4722
+ }})
4723
+ const unsubscribe=props.api.keymap.on?.("state",()=>{if(applying||!props.preferences.ready())
4724
+ return
4725
+ const current=currentPermissionMode(props.api)
4726
+ if(current===undefined||current===observed)
4727
+ return
4728
+ observed=current
4729
+ props.preferences.setAutoApprovePermissions(current)
4730
+ })
4731
+ if(unsubscribe)
4732
+ onCleanup13(unsubscribe)
4733
+ return _$createElement("box")
4734
+ }
4735
+
4736
+
4730
4737
 
4731
4738
  function SettingsFooterButton(props){const icons=useIcons()
4732
4739
  const [hovered,setHovered]=createSignal16(false)
@@ -4734,7 +4741,7 @@ const theme=()=>props.api.theme.current
4734
4741
  return _$createComponent(IconControl,{id:`${PLUGIN_ID}.settings.footer`,get icon(){return icons.icon("settings")
4735
4742
  },get foregroundColor(){return _$memo(()=>!!hovered())()?theme().text:theme().textMuted
4736
4743
  },get backgroundColor(){return _$memo(()=>!!hovered())()?theme().backgroundElement:theme().backgroundPanel
4737
- },onMouseOver:()=>setHovered(true),onMouseOut:()=>setHovered(false),onMouseUp:()=>openSettings(props.api,props.preferences,undefined,props.mcp)
4744
+ },onMouseOver:()=>setHovered(true),onMouseOut:()=>setHovered(false),onMouseUp:()=>openSettings(props.api,props.preferences,undefined,props.mcp,props.skills)
4738
4745
  })
4739
4746
  }
4740
4747
  import {realpathSync} from "fs"
@@ -4798,17 +4805,17 @@ function StartupSessionBinding(props){if(props.api.keymap.on){const unregister=p
4798
4805
  return
4799
4806
  queueMicrotask(()=>void props.controller.start())
4800
4807
  })
4801
- onCleanup13(unregister)
4808
+ onCleanup14(unregister)
4802
4809
  } else
4803
- createEffect10(()=>{if(!props.controller.enabled())
4810
+ createEffect12(()=>{if(!props.controller.enabled())
4804
4811
  return
4805
4812
  const unregister=props.api.keymap.registerLayer({mode:"global",priority:2001,commands:[{name:"session.new",title:"New session",category:"Session",namespace:"palette",enabled:props.controller.enabled,run:()=>void props.controller.start()
4806
4813
  }]
4807
4814
  })
4808
- onCleanup13(unregister)
4815
+ onCleanup14(unregister)
4809
4816
  })
4810
4817
  onMount5(()=>void props.controller.initialize())
4811
- onCleanup13(props.controller.dispose)
4818
+ onCleanup14(props.controller.dispose)
4812
4819
  return _$createElement("box")
4813
4820
  }
4814
4821
  function versionParts(value){const match=/^v?(\d+)\.(\d+)\.(\d+)(?:-([^+]+))?/.exec(value)
@@ -4942,7 +4949,7 @@ if(entries.length===0||disposed)
4942
4949
  return
4943
4950
  show()
4944
4951
  } catch{}})
4945
- onCleanup14(()=>{disposed=true
4952
+ onCleanup15(()=>{disposed=true
4946
4953
  clearTimeout(pending)
4947
4954
  })
4948
4955
  return _$createElement("box")
@@ -5392,7 +5399,7 @@ const colors=()=>sidebarInteractiveColors(api.theme.current,{focused:focused(),h
5392
5399
  const ref=(renderable)=>{unregister?.()
5393
5400
  unregister=interaction?.register({...descriptor,renderable})
5394
5401
  }
5395
- onCleanup15(()=>unregister?.())
5402
+ onCleanup16(()=>unregister?.())
5396
5403
  return{ref,disabled,focused,backgroundColor:()=>colors().backgroundColor,foregroundColor:()=>colors().foregroundColor,onMouseOver:()=>setHovered(true),onMouseOut:()=>setHovered(false),select(event){interaction?.mouseSelect(descriptor.id,event)
5397
5404
  },activate(event){if(interaction)
5398
5405
  return interaction.mouseActivate(descriptor.id,event)
@@ -5449,16 +5456,16 @@ return _el$3
5449
5456
  function createListVisibility(options){const [expanded,setExpanded]=createSignal21(false)
5450
5457
  let previousKey
5451
5458
  let previousLimit
5452
- const canToggle=createMemo9(()=>options.limit()>0&&options.items().length>options.limit())
5459
+ const canToggle=createMemo10(()=>options.limit()>0&&options.items().length>options.limit())
5453
5460
  createComputed(()=>{const key=options.resetKey()
5454
5461
  const limit=options.limit()
5455
5462
  const isToggle=canToggle()
5456
5463
  if(key!==previousKey||limit!==previousLimit||!isToggle)
5457
- untrack2(()=>setExpanded(false))
5464
+ untrack3(()=>setExpanded(false))
5458
5465
  previousKey=key
5459
5466
  previousLimit=limit
5460
5467
  })
5461
- const visible=createMemo9(()=>!canToggle()||expanded()?options.items():options.items().slice(0,options.limit()))
5468
+ const visible=createMemo10(()=>!canToggle()||expanded()?options.items():options.items().slice(0,options.limit()))
5462
5469
  return{visible,expanded,canToggle,hiddenCount:()=>options.items().length-visible().length,showAll:()=>setExpanded(canToggle()),showLess:()=>setExpanded(false)
5463
5470
  }}
5464
5471
 
@@ -5473,7 +5480,7 @@ return{visible,expanded,canToggle,hiddenCount:()=>options.items().length-visible
5473
5480
  function ListVisibilityControl(props){const icons=useIcons()
5474
5481
  const id=`${PLUGIN_ID}.list.${props.section}`
5475
5482
  createComputed2(()=>{const isVisible=props.visibility.canToggle()
5476
- untrack3(()=>{if(!isVisible&&props.interaction?.selectedId()===id){props.interaction.select(`${PLUGIN_ID}.section.${props.section}`)
5483
+ untrack4(()=>{if(!isVisible&&props.interaction?.selectedId()===id){props.interaction.select(`${PLUGIN_ID}.section.${props.section}`)
5477
5484
  }})
5478
5485
  })
5479
5486
  const item=useSidebarItem(props.api,props.interaction,{id,position:()=>({section:props.navigationSection,row:props.row,column:0
@@ -5537,7 +5544,7 @@ const item=useSidebarItem(props.api,props.interaction,{id:props.sectionId??`sect
5537
5544
  const action=props.headerAction?useSidebarItem(props.api,props.interaction,{id:props.headerAction.id,position:()=>({section:props.navigationSection??0,row:0,column:1
5538
5545
  }),disabled:props.headerAction.disabled,activate:props.headerAction.onActivate
5539
5546
  },()=>theme().accent,"control"):undefined
5540
- createEffect11(()=>{props.headerAction?.label()
5547
+ createEffect13(()=>{props.headerAction?.label()
5541
5548
  setActionWidth(undefined)
5542
5549
  })
5543
5550
  const actionLabel=()=>{const label=props.headerAction?.label()??""
@@ -5614,11 +5621,11 @@ return _el$
5614
5621
  })()
5615
5622
  }
5616
5623
  var SectionWithHeaderAction=Section;
5617
- function LspSection(props){const list=createMemo10(()=>[...props.api.state.lsp()].sort((a,b)=>Number(b.status==="error")-Number(a.status==="error")||a.id.localeCompare(b.id)||a.root.localeCompare(b.root)))
5624
+ function LspSection(props){const list=createMemo11(()=>[...props.api.state.lsp()].sort((a,b)=>Number(b.status==="error")-Number(a.status==="error")||a.id.localeCompare(b.id)||a.root.localeCompare(b.root)))
5618
5625
  const visibility=createListVisibility({items:list,limit:()=>props.preferences.sectionItemLimit?.("lsp")??0,resetKey:()=>currentLocation(props.api).key
5619
5626
  })
5620
- const connected=createMemo10(()=>list().filter((item)=>item.status==="connected").length)
5621
- const disabled=createMemo10(()=>props.api.state.config.lsp===false)
5627
+ const connected=createMemo11(()=>list().filter((item)=>item.status==="connected").length)
5628
+ const disabled=createMemo11(()=>props.api.state.config.lsp===false)
5622
5629
  const navigationSection=()=>props.navigationSection??5
5623
5630
  return _$createComponent(Section,{get api(){return props.api
5624
5631
  },get interaction(){return props.interaction
@@ -5657,28 +5664,31 @@ return _el$
5657
5664
 
5658
5665
 
5659
5666
 
5660
- function createMcpSectionModel(props,query){const target=createMemo11(()=>props.controller.target())
5661
- const favorites=createMemo11(()=>props.preferences.favoriteMcpServers?.()??new Set)
5662
- const groups=createMemo11(()=>props.preferences.mcpServerGroups?.()??{})
5663
- const grouped=createMemo11(()=>Object.keys(groups()).length>0)
5664
- const list=createMemo11(()=>buildMcpGroupedView(props.controller.list(target()),favorites(),groups()))
5665
- const filtered=createMemo11(()=>list().filter((item)=>matchesFilter(query(),`${item.name} ${item.assignedGroup ?? ""}`)))
5667
+ function createMcpSectionModel(props,query){const target=createMemo12(()=>props.controller.target())
5668
+ const favorites=createMemo12(()=>props.preferences.favoriteMcpServers?.()??new Set)
5669
+ const groups=createMemo12(()=>props.preferences.mcpServerGroups?.()??{})
5670
+ const grouped=createMemo12(()=>Object.keys(groups()).length>0)
5671
+ const list=createMemo12(()=>buildMcpGroupedView(props.controller.list(target()),favorites(),groups()))
5672
+ const groupItems=(bucket)=>list().filter((item)=>item.bucket===bucket)
5673
+ const filtered=createMemo12(()=>list().filter((item)=>matchesFilter(query(),`${item.name} ${item.assignedGroup ?? ""}`)))
5666
5674
  const visibility=createListVisibility({items:filtered,limit:()=>props.preferences.sectionItemLimit?.("mcp")??0,resetKey:()=>JSON.stringify([target().key,query()])
5667
5675
  })
5668
- const active=createMemo11(()=>list().filter((item)=>item.status==="connected").length)
5669
- const state=createMemo11(()=>props.controller.state(target()))
5670
- const bulk=createMemo11(()=>props.controller.bulkState?.(target())??{action:"connect",status:"idle",completed:0,total:0,failed:[]
5676
+ const active=createMemo12(()=>list().filter((item)=>item.status==="connected").length)
5677
+ const state=createMemo12(()=>props.controller.state(target()))
5678
+ const bulk=createMemo12(()=>props.controller.bulkState?.(target())??{action:"connect",status:"idle",completed:0,total:0,failed:[]
5671
5679
  })
5672
- const bulkRunning=createMemo11(()=>bulk().status==="running")
5673
- const mutationRunning=createMemo11(()=>props.controller.mutating?.(target()))
5674
- const connectable=createMemo11(()=>list().filter((item)=>mcpToggleAction2(item.status)==="connect").length)
5675
- const disconnectable=createMemo11(()=>list().filter((item)=>mcpToggleAction2(item.status)==="disconnect").length)
5676
- const errors=createMemo11(()=>list().filter((item)=>item.status==="failed"||item.status==="needs_auth"||item.status==="needs_client_registration").length)
5677
- const presetName=createMemo11(()=>{const presets=props.preferences.mcpPresets?.()??{}
5680
+ const bulkRunning=createMemo12(()=>bulk().status==="running")
5681
+ const mutationRunning=createMemo12(()=>props.controller.mutating?.(target()))
5682
+ const connectable=createMemo12(()=>list().filter((item)=>mcpToggleAction2(item.status)==="connect").length)
5683
+ const disconnectable=createMemo12(()=>list().filter((item)=>mcpToggleAction2(item.status)==="disconnect").length)
5684
+ const errors=createMemo12(()=>list().filter((item)=>item.status==="failed"||item.status==="needs_auth"||item.status==="needs_client_registration").length)
5685
+ const presetName=createMemo12(()=>{const presets=props.preferences.mcpPresets?.()??{}
5678
5686
  const selected=props.controller.selectedPreset?.(target())
5679
5687
  return selected&&Object.hasOwn(presets,selected)?selected:matchingMcpPreset(list(),presets)
5680
5688
  })
5681
- return{target,favorites,groups,grouped,list,filtered,visibility,active,state,bulk,bulkRunning,mutationRunning,connectable,disconnectable,errors,presetName
5689
+ return{target,favorites,groups,grouped,list,groupNames(bucket){return groupItems(bucket).map((item)=>item.name)
5690
+ },groupAction(bucket){return mcpGroupToggleAction(groupItems(bucket))
5691
+ },filtered,visibility,active,state,bulk,bulkRunning,mutationRunning,connectable,disconnectable,errors,presetName
5682
5692
  }}
5683
5693
 
5684
5694
 
@@ -5691,6 +5701,15 @@ return{target,favorites,groups,grouped,list,filtered,visibility,active,state,bul
5691
5701
 
5692
5702
 
5693
5703
 
5704
+
5705
+
5706
+
5707
+
5708
+
5709
+
5710
+
5711
+
5712
+
5694
5713
 
5695
5714
 
5696
5715
 
@@ -5709,6 +5728,93 @@ _$effect((_$p)=>_$setProp(_el$,"fg",item.foregroundColor(),_$p))
5709
5728
  return _el$
5710
5729
  }})
5711
5730
  }
5731
+ function McpBulkControls(props){const icons=useIcons()
5732
+ const model=props.model
5733
+ const progress=()=>{const state=model.bulk()
5734
+ if(state.action==="preset")
5735
+ return `Applying ${state.preset}`
5736
+ return state.action==="connect"?"Connecting":"Disconnecting"
5737
+ }
5738
+ return [(()=>{var _el$=_$createElement("box")
5739
+ _$setProp(_el$,"flexDirection","row")
5740
+ _$setProp(_el$,"gap",1)
5741
+ _$insert(_el$,_$createComponent(McpBulkAction,{get api(){return props.api
5742
+ },get interaction(){return props.interaction
5743
+ },id:`${PLUGIN_ID}.mcp.connect-all`,get position(){return{section:props.navigationSection,row:2,column:0
5744
+ }},get label(){return `${icons.icon("connected")} Connect all`
5745
+ },get disabled(){return model.bulkRunning()||model.mutationRunning()||model.connectable()===0
5746
+ },onActivate:()=>void props.controller.connectAll(model.target())
5747
+ }),null)
5748
+ _$insert(_el$,_$createComponent(McpBulkAction,{get api(){return props.api
5749
+ },get interaction(){return props.interaction
5750
+ },id:`${PLUGIN_ID}.mcp.disconnect-all`,get position(){return{section:props.navigationSection,row:2,column:1
5751
+ }},get label(){return `${icons.icon("disconnected")} Disconnect all`
5752
+ },get disabled(){return model.bulkRunning()||model.mutationRunning()||model.disconnectable()===0
5753
+ },onActivate:()=>void props.controller.disconnectAll(model.target())
5754
+ }),null)
5755
+ _$effect((_$p)=>_$setProp(_el$,"paddingBottom",model.bulkRunning()||model.bulk().status==="error"?1:0,_$p))
5756
+ return _el$
5757
+ })(),_$createComponent(Show11,{get when(){return model.bulkRunning()
5758
+ },get children(){var _el$2=_$createElement("text"),_el$3=_$createTextNode(` `),_el$4=_$createTextNode(`/`),_el$5=_$createTextNode(`\u2026`)
5759
+ _$insertNode(_el$2,_el$3)
5760
+ _$insertNode(_el$2,_el$4)
5761
+ _$insertNode(_el$2,_el$5)
5762
+ _$insert(_el$2,progress,_el$3)
5763
+ _$insert(_el$2,()=>model.bulk().completed,_el$4)
5764
+ _$insert(_el$2,()=>model.bulk().total,_el$5)
5765
+ _$effect((_$p)=>_$setProp(_el$2,"fg",props.api.theme.current.textMuted,_$p))
5766
+ return _el$2
5767
+ }}),_$createComponent(Show11,{get when(){return model.bulk().status==="error"
5768
+ },get children(){return _$createComponent(McpBulkAction,{get api(){return props.api
5769
+ },get interaction(){return props.interaction
5770
+ },id:`${PLUGIN_ID}.mcp.retry-all`,get position(){return{section:props.navigationSection,row:3,column:0
5771
+ }},get label(){return `${icons.icon("retry")} Retry ${model.bulk().failed.length} failed`
5772
+ },disabled:false,onActivate:()=>void props.controller.retryBulk(model.target())
5773
+ })
5774
+ }})]
5775
+ }
5776
+
5777
+
5778
+
5779
+
5780
+
5781
+
5782
+
5783
+
5784
+ function McpGroupHeader(props){const icons=useIcons()
5785
+ const theme=()=>props.api.theme.current
5786
+ const id=()=>`${PLUGIN_ID}.mcp.group.${props.bucket}`
5787
+ const item=useSidebarItem(props.api,props.interaction,{id:id(),position:()=>props.position,disabled:()=>props.disabled||!props.action,activate:props.onToggle
5788
+ })
5789
+ return _$createComponent(SelectionBox,{ref:(node)=>item.ref(node),get id(){return id()
5790
+ },height:1,get marginTop(){return props.marginTop
5791
+ },flexDirection:"row",justifyContent:"space-between",gap:1,get backgroundColor(){return item.backgroundColor()
5792
+ },get onMouseOver(){return item.onMouseOver
5793
+ },get onMouseOut(){return item.onMouseOut
5794
+ },onMouseUp:(event)=>{event.stopPropagation()
5795
+ item.activate(event)
5796
+ },get children(){return [(()=>{var _el$=_$createElement("text"),_el$2=_$createTextNode(` (`),_el$3=_$createTextNode(`)`)
5797
+ _$insertNode(_el$,_el$2)
5798
+ _$insertNode(_el$,_el$3)
5799
+ _$setProp(_el$,"flexGrow",1)
5800
+ _$setProp(_el$,"minWidth",0)
5801
+ _$setProp(_el$,"wrapMode","none")
5802
+ _$setProp(_el$,"truncate",true)
5803
+ _$insert(_el$,()=>props.bucket,_el$2)
5804
+ _$insert(_el$,()=>props.count,_el$3)
5805
+ _$effect((_$p)=>_$setProp(_el$,"fg",item.focused()?item.foregroundColor():theme().textMuted,_$p))
5806
+ return _el$
5807
+ })(),(()=>{var _el$4=_$createElement("text")
5808
+ _$setProp(_el$4,"flexShrink",0)
5809
+ _$setProp(_el$4,"wrapMode","none")
5810
+ _$insert(_el$4,(()=>{var _c$=_$memo(()=>!!props.action)
5811
+ return()=>_c$()?`${icons.icon(props.action === "connect" ? "connected" : "disconnected")} ${props.action === "connect" ? "Connect" : "Disconnect"}`:""
5812
+ })())
5813
+ _$effect((_$p)=>_$setProp(_el$4,"fg",item.focused()?item.foregroundColor():props.disabled?theme().textMuted:theme().accent,_$p))
5814
+ return _el$4
5815
+ })()]
5816
+ }})
5817
+ }
5712
5818
 
5713
5819
 
5714
5820
 
@@ -5741,7 +5847,7 @@ return status==="connected"?"connected":"disconnected"
5741
5847
  function RequestErrorRow(props){const icons=useIcons()
5742
5848
  const item=useSidebarItem(props.api,props.interaction,{id:props.id,position:()=>props.position,disabled:()=>!props.state.error?.retryable||props.state.status==="loading"||props.state.status==="refreshing",activate:props.onRetry
5743
5849
  })
5744
- return _$createComponent(Show11,{get when(){return props.state.error
5850
+ return _$createComponent(Show12,{get when(){return props.state.error
5745
5851
  },children:(error)=>_$createComponent(SelectionBox,{ref:(node)=>item.ref(node),get id(){return props.id
5746
5852
  },flexDirection:"row",gap:1,paddingLeft:1,paddingRight:1,get backgroundColor(){return item.backgroundColor()
5747
5853
  },get onMouseOver(){return item.onMouseOver
@@ -5756,7 +5862,7 @@ _$insert(_el$,()=>icons.icon("error"),_el$2)
5756
5862
  _$insert(_el$,()=>error().message,null)
5757
5863
  _$effect((_$p)=>_$setProp(_el$,"fg",item.focused()?item.foregroundColor():props.api.theme.current.error,_$p))
5758
5864
  return _el$
5759
- })(),_$createComponent(Show11,{get when(){return error().retryable
5865
+ })(),_$createComponent(Show12,{get when(){return error().retryable
5760
5866
  },get children(){var _el$3=_$createElement("text"),_el$4=_$createTextNode(` Retry`)
5761
5867
  _$insertNode(_el$3,_el$4)
5762
5868
  _$setProp(_el$3,"flexShrink",0)
@@ -5771,7 +5877,7 @@ function SectionRequestBody(props){const icons=useIcons()
5771
5877
  const pending=()=>props.state.status==="loading"
5772
5878
  return(()=>{var _el$5=_$createElement("box")
5773
5879
  _$insert(_el$5,_$createComponent(RequestErrorRow,props),null)
5774
- _$insert(_el$5,_$createComponent(Show11,{get when(){return _$memo(()=>!!pending())()&&!props.hasItems
5880
+ _$insert(_el$5,_$createComponent(Show12,{get when(){return _$memo(()=>!!pending())()&&!props.hasItems
5775
5881
  },get children(){var _el$6=_$createElement("text"),_el$7=_$createTextNode(` `)
5776
5882
  _$insertNode(_el$6,_el$7)
5777
5883
  _$insert(_el$6,()=>icons.icon("pending"),_el$7)
@@ -5779,10 +5885,10 @@ _$insert(_el$6,()=>props.loading,null)
5779
5885
  _$effect((_$p)=>_$setProp(_el$6,"fg",props.api.theme.current.textMuted,_$p))
5780
5886
  return _el$6
5781
5887
  }}),null)
5782
- _$insert(_el$5,_$createComponent(Show11,{get when(){return props.hasItems
5888
+ _$insert(_el$5,_$createComponent(Show12,{get when(){return props.hasItems
5783
5889
  },get children(){return props.children
5784
5890
  }}),null)
5785
- _$insert(_el$5,_$createComponent(Show11,{get when(){return _$memo(()=>!!((props.state.status==="ready"||props.state.status==="refreshing")&&!props.hasItems))()&&!props.state.error
5891
+ _$insert(_el$5,_$createComponent(Show12,{get when(){return _$memo(()=>!!((props.state.status==="ready"||props.state.status==="refreshing")&&!props.hasItems))()&&!props.state.error
5786
5892
  },get children(){var _el$8=_$createElement("text"),_el$9=_$createTextNode(` `)
5787
5893
  _$insertNode(_el$8,_el$9)
5788
5894
  _$insert(_el$8,()=>icons.icon("info"),_el$9)
@@ -5900,7 +6006,7 @@ props.interaction.leaveFilter(input)
5900
6006
  else
5901
6007
  input?.blur()
5902
6008
  }
5903
- onCleanup16(()=>unregisterInput?.())
6009
+ onCleanup17(()=>unregisterInput?.())
5904
6010
  return _$createComponent(SelectionBox,{ref:(node)=>item.ref(node),get id(){return props.id
5905
6011
  },flexDirection:"row",gap:1,marginTop:1,marginBottom:1,paddingLeft:1,paddingRight:1,get backgroundColor(){return _$memo(()=>!!highlighted())()?theme().primary:item.backgroundColor()
5906
6012
  },get onMouseOver(){return item.onMouseOver
@@ -5938,7 +6044,7 @@ return _p$
5938
6044
  },{e:undefined,t:undefined,a:undefined,o:undefined,i:undefined,n:undefined,s:undefined,h:undefined
5939
6045
  })
5940
6046
  return _el$2
5941
- })(),_$createComponent(Show12,{get when(){return props.query
6047
+ })(),_$createComponent(Show13,{get when(){return props.query
5942
6048
  },get children(){var _el$3=_$createElement("text")
5943
6049
  _$setProp(_el$3,"flexShrink",0)
5944
6050
  _$setProp(_el$3,"onMouseDown",()=>props.onInput(""))
@@ -5958,82 +6064,47 @@ _$effect((_$p)=>_$setProp(_el$,"gap",props.density==="comfortable"?1:0,_$p))
5958
6064
  return _el$
5959
6065
  })()
5960
6066
  }
5961
- function McpSectionContent(props){const icons=useIcons()
5962
- const model=props.model
6067
+ function McpSectionContent(props){const model=props.model
5963
6068
  return _$createComponent(SectionRequestBody,{get api(){return props.api
5964
6069
  },get interaction(){return props.interaction
5965
6070
  },id:`${PLUGIN_ID}.retry.mcp`,get position(){return{section:props.navigationSection,row:1,column:0
5966
6071
  }},get state(){return model.state()
5967
6072
  },get hasItems(){return model.list().length>0
5968
- },empty:"No MCP servers",loading:"Loading MCP servers\u2026",onRetry:()=>void props.controller.retry(model.target()),get children(){var _el$=_$createElement("box"),_el$2=_$createElement("box")
5969
- _$insertNode(_el$,_el$2)
5970
- _$setProp(_el$2,"flexDirection","row")
5971
- _$setProp(_el$2,"gap",1)
5972
- _$insert(_el$2,_$createComponent(McpBulkAction,{get api(){return props.api
6073
+ },empty:"No MCP servers",loading:"Loading MCP servers\u2026",onRetry:()=>void props.controller.retry(model.target()),get children(){var _el$=_$createElement("box")
6074
+ _$insert(_el$,_$createComponent(McpBulkControls,{get api(){return props.api
5973
6075
  },get interaction(){return props.interaction
5974
- },id:`${PLUGIN_ID}.mcp.connect-all`,get position(){return{section:props.navigationSection,row:2,column:0
5975
- }},get label(){return `${icons.icon("connected")} Connect all`
5976
- },get disabled(){return model.bulkRunning()||model.mutationRunning()||model.connectable()===0
5977
- },onActivate:()=>void props.controller.connectAll(model.target())
5978
- }),null)
5979
- _$insert(_el$2,_$createComponent(McpBulkAction,{get api(){return props.api
5980
- },get interaction(){return props.interaction
5981
- },id:`${PLUGIN_ID}.mcp.disconnect-all`,get position(){return{section:props.navigationSection,row:2,column:1
5982
- }},get label(){return `${icons.icon("disconnected")} Disconnect all`
5983
- },get disabled(){return model.bulkRunning()||model.mutationRunning()||model.disconnectable()===0
5984
- },onActivate:()=>void props.controller.disconnectAll(model.target())
6076
+ },get controller(){return props.controller
6077
+ },get navigationSection(){return props.navigationSection
6078
+ },model
5985
6079
  }),null)
5986
- _$insert(_el$,_$createComponent(Show13,{get when(){return model.bulkRunning()
5987
- },get children(){var _el$3=_$createElement("text"),_el$4=_$createTextNode(` `),_el$5=_$createTextNode(`/`),_el$6=_$createTextNode(`\u2026`)
5988
- _$insertNode(_el$3,_el$4)
5989
- _$insertNode(_el$3,_el$5)
5990
- _$insertNode(_el$3,_el$6)
5991
- _$insert(_el$3,(()=>{var _c$=_$memo(()=>model.bulk().action==="connect")
5992
- return()=>_c$()?"Connecting":_$memo(()=>model.bulk().action==="disconnect")()?"Disconnecting":`Applying ${model.bulk().preset}`
5993
- })(),_el$4)
5994
- _$insert(_el$3,()=>model.bulk().completed,_el$5)
5995
- _$insert(_el$3,()=>model.bulk().total,_el$6)
5996
- _$effect((_$p)=>_$setProp(_el$3,"fg",props.api.theme.current.textMuted,_$p))
5997
- return _el$3
5998
- }}),null)
5999
- _$insert(_el$,_$createComponent(Show13,{get when(){return model.bulk().status==="error"
6000
- },get children(){return _$createComponent(McpBulkAction,{get api(){return props.api
6001
- },get interaction(){return props.interaction
6002
- },id:`${PLUGIN_ID}.mcp.retry-all`,get position(){return{section:props.navigationSection,row:3,column:0
6003
- }},get label(){return `${icons.icon("retry")} Retry ${model.bulk().failed.length} failed`
6004
- },disabled:false,onActivate:()=>void props.controller.retryBulk(model.target())
6005
- })
6006
- }}),null)
6007
6080
  _$insert(_el$,_$createComponent(SectionFilter,{get api(){return props.api
6008
6081
  },get interaction(){return props.interaction
6009
6082
  },id:`${PLUGIN_ID}.filter.mcp`,get position(){return{section:props.navigationSection,row:4,column:0
6010
6083
  }},get query(){return props.query
6011
6084
  },placeholder:"Filter MCP...",get onInput(){return props.onQuery
6012
6085
  }}),null)
6013
- _$insert(_el$,_$createComponent(Show13,{get when(){return model.filtered().length>0
6014
- },get fallback(){return(()=>{var _el$7=_$createElement("text")
6015
- _$insertNode(_el$7,_$createTextNode(`No matching MCP servers`))
6016
- _$effect((_$p)=>_$setProp(_el$7,"fg",props.api.theme.current.textMuted,_$p))
6017
- return _el$7
6086
+ _$insert(_el$,_$createComponent(Show14,{get when(){return model.filtered().length>0
6087
+ },get fallback(){return(()=>{var _el$2=_$createElement("text")
6088
+ _$insertNode(_el$2,_$createTextNode(`No matching MCP servers`))
6089
+ _$effect((_$p)=>_$setProp(_el$2,"fg",props.api.theme.current.textMuted,_$p))
6090
+ return _el$2
6018
6091
  })()
6019
6092
  },get children(){return [_$createComponent(SidebarRowList,{get density(){return props.preferences.rowDensity?.()??"compact"
6020
6093
  },get children(){return _$createComponent(For13,{get each(){return model.visibility.visible()
6021
- },children:(item,index)=>[_$createComponent(Show13,{get when(){return _$memo(()=>!!model.grouped())()&&(index()===0||model.visibility.visible()[index()-1]?.bucket!==item.bucket)
6022
- },get children(){var _el$9=_$createElement("text")
6023
- _$setProp(_el$9,"height",1)
6024
- _$setProp(_el$9,"wrapMode","none")
6025
- _$setProp(_el$9,"truncate",true)
6026
- _$insert(_el$9,()=>item.bucket)
6027
- _$effect((_p$)=>{var _v$=index()>0?1:0,_v$2=props.api.theme.current.textMuted
6028
- _v$!==_p$.e&&(_p$.e=_$setProp(_el$9,"marginTop",_v$,_p$.e))
6029
- _v$2!==_p$.t&&(_p$.t=_$setProp(_el$9,"fg",_v$2,_p$.t))
6030
- return _p$
6031
- },{e:undefined,t:undefined
6094
+ },children:(item,index)=>[_$createComponent(Show14,{get when(){return _$memo(()=>!!model.grouped())()&&(index()===0||model.visibility.visible()[index()-1]?.bucket!==item.bucket)
6095
+ },get children(){return _$createComponent(McpGroupHeader,{get api(){return props.api
6096
+ },get interaction(){return props.interaction
6097
+ },get bucket(){return item.bucket
6098
+ },get count(){return model.groupNames(item.bucket).length
6099
+ },get action(){return model.groupAction(item.bucket)
6100
+ },get disabled(){return model.bulkRunning()||model.mutationRunning()
6101
+ },get marginTop(){return index()>0?1:0
6102
+ },get position(){return{section:props.navigationSection,row:9 + index()*3,column:0
6103
+ }},onToggle:()=>void props.controller.toggleGroup(item.bucket,model.groupNames(item.bucket),model.target())
6032
6104
  })
6033
- return _el$9
6034
6105
  }}),_$createComponent(McpRow,{get api(){return props.api
6035
6106
  },get interaction(){return props.interaction
6036
- },item,get position(){return{section:props.navigationSection,row:10 + index()*2,column:0
6107
+ },item,get position(){return{section:props.navigationSection,row:10 + index()*3,column:0
6037
6108
  }},get state(){return props.controller.serverState(item.name,model.target())
6038
6109
  },get disabled(){return model.bulkRunning()
6039
6110
  },onToggle:()=>void props.controller.toggle(item.name).catch(()=>{}),onRetry:()=>void props.controller.retryServer(item.name,model.target())?.catch(()=>{}),get favorite(){return model.favorites().has(item.name)
@@ -6045,11 +6116,10 @@ return _el$9
6045
6116
  }}),_$createComponent(ListVisibilityControl,{get api(){return props.api
6046
6117
  },get interaction(){return props.interaction
6047
6118
  },section:"mcp",get navigationSection(){return props.navigationSection
6048
- },get row(){return 10 + model.visibility.visible().length*2
6119
+ },get row(){return 10 + model.visibility.visible().length*3
6049
6120
  },get visibility(){return model.visibility
6050
6121
  }})]
6051
6122
  }}),null)
6052
- _$effect((_$p)=>_$setProp(_el$2,"paddingBottom",model.bulkRunning()||model.bulk().status==="error"?1:0,_$p))
6053
6123
  return _el$
6054
6124
  }})
6055
6125
  }
@@ -6057,7 +6127,7 @@ function McpSection(props){const icons=useIcons()
6057
6127
  const [query,setQuery]=createSignal24("")
6058
6128
  const model=createMcpSectionModel(props,query)
6059
6129
  const navigationSection=()=>props.navigationSection??6
6060
- const summary=createMemo12(()=>`${model.active()}/${model.list().length}${model.errors() ? ` \xB7 ${model.errors()} ${icons.icon("error")}` : ""}`)
6130
+ const summary=createMemo13(()=>`${model.active()}/${model.list().length}${model.errors() ? ` \xB7 ${model.errors()} ${icons.icon("error")}` : ""}`)
6061
6131
  return _$createComponent(SectionWithHeaderAction,{get api(){return props.api
6062
6132
  },get interaction(){return props.interaction
6063
6133
  },sectionId:`${PLUGIN_ID}.section.mcp`,get navigationSection(){return navigationSection()
@@ -6092,11 +6162,11 @@ return _$createComponent(SectionWithHeaderAction,{get api(){return props.api
6092
6162
  function QuickActionRow(props){const icons=useIcons()
6093
6163
  const theme=()=>props.api.theme.current
6094
6164
  const [width,setWidth]=createSignal25(0)
6095
- const shortcut=createMemo13(()=>{const bindings=props.api.keymap.getCommandBindings({visibility:"registered",commands:[props.action.command]
6165
+ const shortcut=createMemo14(()=>{const bindings=props.api.keymap.getCommandBindings({visibility:"registered",commands:[props.action.command]
6096
6166
  })
6097
6167
  return props.api.keys.formatBindings(bindings.get(props.action.command))
6098
6168
  })
6099
- const visibleShortcut=createMemo13(()=>{const value=shortcut()
6169
+ const visibleShortcut=createMemo14(()=>{const value=shortcut()
6100
6170
  return value&&width()>=Bun.stringWidth(props.action.label) + Bun.stringWidth(value) + 9?value:undefined
6101
6171
  })
6102
6172
  function run(){if(props.action.command==="session.new"&&props.onNewSession?.())
@@ -6139,7 +6209,7 @@ _$insert(_el$2,()=>props.action.label)
6139
6209
  _$effect((_$p)=>_$setProp(_el$2,"fg",row.foregroundColor(),_$p))
6140
6210
  return _el$2
6141
6211
  })()
6142
- },get metadata(){return _$createComponent(Show14,{get when(){return visibleShortcut()
6212
+ },get metadata(){return _$createComponent(Show15,{get when(){return visibleShortcut()
6143
6213
  },children:(value)=>(()=>{var _el$3=_$createElement("text")
6144
6214
  _$setProp(_el$3,"flexShrink",0)
6145
6215
  _$setProp(_el$3,"wrapMode","none")
@@ -6148,7 +6218,7 @@ _$effect((_$p)=>_$setProp(_el$3,"fg",row.focused()?row.foregroundColor():theme()
6148
6218
  return _el$3
6149
6219
  })()
6150
6220
  })
6151
- },get details(){return _$createComponent(Show14,{get when(){return props.disabled
6221
+ },get details(){return _$createComponent(Show15,{get when(){return props.disabled
6152
6222
  },children:(reason)=>(()=>{var _el$4=_$createElement("text")
6153
6223
  _$setProp(_el$4,"wrapMode","word")
6154
6224
  _$insert(_el$4,reason)
@@ -6167,7 +6237,7 @@ return _el$4
6167
6237
  }})
6168
6238
  }
6169
6239
  function QuickActionsSection(props){const commandRevision=createQuickActionRevision(props.api)
6170
- const actions=createMemo14(()=>{commandRevision()
6240
+ const actions=createMemo15(()=>{commandRevision()
6171
6241
  return orderQuickActionIds(props.preferences.quickActionOrder?.()??QUICK_ACTIONS.map((action)=>action.command),props.preferences.favoriteQuickActions?.()??new Set).flatMap((id)=>{const action=QUICK_ACTIONS.find((candidate)=>candidate.command===id)
6172
6242
  return action&&props.preferences.quickActionVisible?.(id)!==false?[{...action,label:quickActionLabel(props.api,action),disabled:quickActionDisabledReason(props.api,action)
6173
6243
  }]:[]
@@ -6182,7 +6252,7 @@ return _$createComponent(Section,{get api(){return props.api
6182
6252
  },title:"QUICK ACTIONS",section:"quick_actions",get summary(){return String(actions().length)
6183
6253
  },get open(){return props.preferences.expanded().quick_actions
6184
6254
  },onToggle:()=>props.preferences.toggleSectionExpanded("quick_actions"),get children(){return [_$createComponent(SidebarRowList,{get density(){return props.preferences.rowDensity?.()??"compact"
6185
- },get children(){return [_$createComponent(Show15,{get when(){return actions().length===0
6255
+ },get children(){return [_$createComponent(Show16,{get when(){return actions().length===0
6186
6256
  },get children(){var _el$=_$createElement("text")
6187
6257
  _$insertNode(_el$,_$createTextNode(`No quick actions selected`))
6188
6258
  _$effect((_$p)=>_$setProp(_el$,"fg",props.api.theme.current.textMuted,_$p))
@@ -6299,8 +6369,8 @@ unregisterBinding=undefined
6299
6369
  unregisterCommands()
6300
6370
  }}}
6301
6371
  function SidebarToggleBinding(props){const shortcuts=createSidebarShortcutMode(props.api)
6302
- createEffect12(()=>shortcuts.bind(props.preferences.toggleKey()))
6303
- onCleanup17(shortcuts.dispose)
6372
+ createEffect14(()=>shortcuts.bind(props.preferences.toggleKey()))
6373
+ onCleanup18(shortcuts.dispose)
6304
6374
  return _$createElement("box")
6305
6375
  }
6306
6376
  function SidebarFocusBinding(props){const commands=props.interaction.baseCommands()
@@ -6308,11 +6378,11 @@ const unregisterCommands=props.api.keymap.registerLayer({commands:[...commands,.
6308
6378
  })=>({name:name.replace(PLUGIN_ID,()=>LEGACY_PLUGIN_ID),run,enabled
6309
6379
  }))]
6310
6380
  })
6311
- onCleanup17(unregisterCommands)
6312
- createEffect12(()=>{const unregister=props.api.keymap.registerLayer({bindings:[{key:props.preferences.focusKey(),cmd:FOCUS_COMMAND
6381
+ onCleanup18(unregisterCommands)
6382
+ createEffect14(()=>{const unregister=props.api.keymap.registerLayer({bindings:[{key:props.preferences.focusKey(),cmd:FOCUS_COMMAND
6313
6383
  }]
6314
6384
  })
6315
- onCleanup17(unregister)
6385
+ onCleanup18(unregister)
6316
6386
  })
6317
6387
  return _$createElement("box")
6318
6388
  }
@@ -6334,22 +6404,19 @@ return _$createElement("box")
6334
6404
 
6335
6405
 
6336
6406
 
6337
- function createSkillSectionModel(props,query){const target=createMemo15(()=>props.controller.target())
6338
- const recent=createMemo15(()=>new Map((props.preferences.recentSkills?.()??[]).map((location,index)=>[location,index])))
6339
- const list=createMemo15(()=>{const favorites=props.preferences.favoriteSkills?.()??new Set
6340
- return [...props.controller.list(target())].sort((left,right)=>{const isLeftFavorite=favorites.has(left.location)
6341
- const isRightFavorite=favorites.has(right.location)
6342
- return Number(isRightFavorite)-Number(isLeftFavorite)||(isLeftFavorite?0:(recent().get(left.location)??Infinity)-(recent().get(right.location)??Infinity))||left.name.localeCompare(right.name)
6343
- }).map((item)=>({...item}))
6344
- })
6345
- const filtered=createMemo15(()=>list().filter((item)=>matchesFilter(query(),item.name,item.description)))
6407
+ function createSkillSectionModel(props,query){const target=createMemo16(()=>props.controller.target())
6408
+ const recent=createMemo16(()=>new Map((props.preferences.recentSkills?.()??[]).map((location,index)=>[location,index])))
6409
+ const groups=createMemo16(()=>props.preferences.skillGroups?.()??{})
6410
+ const grouped=createMemo16(()=>Object.keys(groups()).length>0)
6411
+ const list=createMemo16(()=>buildSkillGroupedView(props.controller.list(target()),props.preferences.favoriteSkills?.()??new Set,groups(),recent()))
6412
+ const filtered=createMemo16(()=>list().filter((item)=>matchesFilter(query(),item.name,item.description,item.assignedGroup)))
6346
6413
  const visibility=createListVisibility({items:filtered,limit:()=>props.preferences.sectionItemLimit?.("skills")??0,resetKey:()=>JSON.stringify([target().key,query()])
6347
6414
  })
6348
- const state=createMemo15(()=>props.controller.state(target()))
6349
- createEffect13(()=>{const current=target()
6350
- const deactivate=untrack4(()=>props.controller.activate?.(current)??(()=>{}))
6351
- onCleanup18(deactivate)
6352
- untrack4(()=>void props.controller.refresh(current).catch(()=>{}))
6415
+ const state=createMemo16(()=>props.controller.state(target()))
6416
+ createEffect15(()=>{const current=target()
6417
+ const deactivate=untrack5(()=>props.controller.activate?.(current)??(()=>{}))
6418
+ onCleanup19(deactivate)
6419
+ untrack5(()=>void props.controller.refresh(current).catch(()=>{}))
6353
6420
  })
6354
6421
  async function useSkill(item){try{const isInserted=await props.controller.use(target(),item.name)
6355
6422
  if(isInserted)
@@ -6359,11 +6426,13 @@ return
6359
6426
  props.api.ui.toast({variant:"error",title:"Skills",message:error instanceof Error?error.message:`Failed to insert /${item.name}`,duration:5000
6360
6427
  })
6361
6428
  }}
6362
- function skillGroup(item){if(props.preferences.isFavoriteSkill?.(item))
6429
+ function skillGroup(item){if(grouped())
6430
+ return item.bucket
6431
+ if(props.preferences.isFavoriteSkill?.(item))
6363
6432
  return "favorite"
6364
6433
  return recent().has(item.location)?"recent":"other"
6365
6434
  }
6366
- return{target,recent,list,filtered,visibility,state,useSkill,skillGroup}}
6435
+ return{target,recent,grouped,list,filtered,visibility,state,useSkill,skillGroup}}
6367
6436
 
6368
6437
 
6369
6438
 
@@ -6445,7 +6514,7 @@ _$insert(_el$,_$createComponent(SectionFilter,{get api(){return props.api
6445
6514
  }},get query(){return query()
6446
6515
  },placeholder:"Filter skills...",onInput:setQuery
6447
6516
  }),null)
6448
- _$insert(_el$,_$createComponent(Show16,{get when(){return model.filtered().length>0
6517
+ _$insert(_el$,_$createComponent(Show17,{get when(){return model.filtered().length>0
6449
6518
  },get fallback(){return(()=>{var _el$2=_$createElement("text")
6450
6519
  _$insertNode(_el$2,_$createTextNode(`No matching skills`))
6451
6520
  _$effect((_$p)=>_$setProp(_el$2,"fg",props.api.theme.current.textMuted,_$p))
@@ -6453,20 +6522,33 @@ return _el$2
6453
6522
  })()
6454
6523
  },get children(){return [_$createComponent(SidebarRowList,{get density(){return props.preferences.rowDensity?.()??"compact"
6455
6524
  },get children(){return _$createComponent(For15,{get each(){return model.visibility.visible()
6456
- },children:(item,index)=>_$createComponent(SkillRow,{get api(){return props.api
6525
+ },children:(item,index)=>[_$createComponent(Show17,{get when(){return _$memo(()=>!!model.grouped())()&&(index()===0||model.visibility.visible()[index()-1]?.bucket!==item.bucket)
6526
+ },get children(){var _el$4=_$createElement("text")
6527
+ _$setProp(_el$4,"height",1)
6528
+ _$setProp(_el$4,"wrapMode","none")
6529
+ _$setProp(_el$4,"truncate",true)
6530
+ _$insert(_el$4,()=>item.bucket)
6531
+ _$effect((_p$)=>{var _v$=index()>0?1:0,_v$2=props.api.theme.current.textMuted
6532
+ _v$!==_p$.e&&(_p$.e=_$setProp(_el$4,"marginTop",_v$,_p$.e))
6533
+ _v$2!==_p$.t&&(_p$.t=_$setProp(_el$4,"fg",_v$2,_p$.t))
6534
+ return _p$
6535
+ },{e:undefined,t:undefined
6536
+ })
6537
+ return _el$4
6538
+ }}),_$createComponent(SkillRow,{get api(){return props.api
6457
6539
  },get interaction(){return props.interaction
6458
- },item,get position(){return{section:navigationSection(),row:10 + index(),column:0
6540
+ },item,get position(){return{section:navigationSection(),row:10 + index()*(model.grouped()?2:1),column:0
6459
6541
  }},onUse:()=>selectSkill(item),get recent(){return model.recent().has(item.location)
6460
6542
  },get favorite(){return props.preferences.isFavoriteSkill?.(item)??false
6461
6543
  },get favoriteDisabled(){return props.preferences.ready?.()===false
6462
- },get separator(){return _$memo(()=>index()>0)()&&model.skillGroup(model.visibility.visible()[index()-1])!==model.skillGroup(item)
6544
+ },get separator(){return _$memo(()=>!!(!model.grouped()&&index()>0))()&&model.skillGroup(model.visibility.visible()[index()-1])!==model.skillGroup(item)
6463
6545
  },onToggleFavorite:()=>props.preferences.toggleFavoriteSkill?.(item)
6464
- })
6546
+ })]
6465
6547
  })
6466
6548
  }}),_$createComponent(ListVisibilityControl,{get api(){return props.api
6467
6549
  },get interaction(){return props.interaction
6468
6550
  },section:"skills",get navigationSection(){return navigationSection()
6469
- },get row(){return 10 + model.visibility.visible().length
6551
+ },get row(){return 10 + model.visibility.visible().length*(model.grouped()?2:1)
6470
6552
  },get visibility(){return model.visibility
6471
6553
  }})]
6472
6554
  }}),null)
@@ -6484,35 +6566,35 @@ return _el$
6484
6566
 
6485
6567
 
6486
6568
 
6487
- function createSubagentSectionModel(props){const list=createMemo16(()=>props.controller.list(props.sessionID))
6488
- const recent=createMemo16(()=>props.controller.recent?.(props.sessionID)??[])
6489
- const rows=createMemo16(()=>buildSubagentView(list(),recent()))
6569
+ function createSubagentSectionModel(props){const list=createMemo17(()=>props.controller.list(props.sessionID))
6570
+ const recent=createMemo17(()=>props.controller.recent?.(props.sessionID)??[])
6571
+ const rows=createMemo17(()=>buildSubagentView(list(),recent()))
6490
6572
  const [query,setQuery]=createSignal27("")
6491
6573
  const [mode,setMode]=createSignal27("all")
6492
- const counts=createMemo16(()=>countSubagentView(rows(),query()))
6493
- const tabs=createMemo16(()=>["all","active","recent",...counts().errors>0?["errors"]:[]])
6494
- const filtered=createMemo16(()=>filterSubagentView(rows(),mode(),query()))
6495
- const parentID=createMemo16(()=>props.api.state?.session?.get(props.sessionID)?.parentID)
6496
- const targetKey=createMemo16(()=>props.controller.target?.(props.sessionID).key??props.sessionID)
6497
- createEffect14(()=>{targetKey()
6574
+ const counts=createMemo17(()=>countSubagentView(rows(),query()))
6575
+ const tabs=createMemo17(()=>["all","active","recent",...counts().errors>0?["errors"]:[]])
6576
+ const filtered=createMemo17(()=>filterSubagentView(rows(),mode(),query()))
6577
+ const parentID=createMemo17(()=>props.api.state?.session?.get(props.sessionID)?.parentID)
6578
+ const targetKey=createMemo17(()=>props.controller.target?.(props.sessionID).key??props.sessionID)
6579
+ createEffect16(()=>{targetKey()
6498
6580
  setQuery("")
6499
6581
  setMode("all")
6500
6582
  })
6501
- createEffect14(()=>{if(mode()!=="all"&&counts()[mode()]===0)
6583
+ createEffect16(()=>{if(mode()!=="all"&&counts()[mode()]===0)
6502
6584
  setMode("all")
6503
6585
  })
6504
6586
  const visibility=createListVisibility({items:filtered,limit:()=>props.preferences.sectionItemLimit?.("subagents")??0,resetKey:()=>JSON.stringify([targetKey(),query(),mode()])
6505
6587
  })
6506
- const clockKey=createMemo16(()=>props.preferences.expanded().subagents&&visibility.visible().some((item)=>item.status.type!=="idle")?targetKey():undefined)
6588
+ const clockKey=createMemo17(()=>props.preferences.expanded().subagents&&visibility.visible().some((item)=>item.status.type!=="idle")?targetKey():undefined)
6507
6589
  const now=createSubagentClock(clockKey)
6508
- const byId=createMemo16(()=>new Map(visibility.visible().map((item)=>[item.session.id,item])))
6509
- const ids=createMemo16(()=>visibility.visible().map((item)=>item.session.id))
6510
- const state=createMemo16(()=>props.controller.state(props.sessionID))
6511
- createEffect14(()=>{const sessionID=props.sessionID
6590
+ const byId=createMemo17(()=>new Map(visibility.visible().map((item)=>[item.session.id,item])))
6591
+ const ids=createMemo17(()=>visibility.visible().map((item)=>item.session.id))
6592
+ const state=createMemo17(()=>props.controller.state(props.sessionID))
6593
+ createEffect16(()=>{const sessionID=props.sessionID
6512
6594
  targetKey()
6513
- const deactivate=untrack5(()=>props.controller.activate?.(sessionID)??(()=>{}))
6514
- onCleanup19(deactivate)
6515
- untrack5(()=>void props.controller.refresh(sessionID).catch(()=>{}))
6595
+ const deactivate=untrack6(()=>props.controller.activate?.(sessionID)??(()=>{}))
6596
+ onCleanup20(deactivate)
6597
+ untrack6(()=>void props.controller.refresh(sessionID).catch(()=>{}))
6516
6598
  })
6517
6599
  return{list,recent,rows,query,setQuery,mode,setMode,counts,tabs,filtered,parentID,visibility,now,byId,ids,state
6518
6600
  }}
@@ -6567,7 +6649,7 @@ return()=>_c$()?`${props.item.run.startedBeforeObservation ? `${icons.icon("rece
6567
6649
  _$effect((_$p)=>_$setProp(_el$3,"fg",row.focused()?row.foregroundColor():theme().textMuted,_$p))
6568
6650
  return _el$3
6569
6651
  })()
6570
- },get details(){return [_$createComponent(Show17,{get when(){return props.item.run?.errorMessage
6652
+ },get details(){return [_$createComponent(Show18,{get when(){return props.item.run?.errorMessage
6571
6653
  },get children(){var _el$4=_$createElement("text"),_el$5=_$createTextNode(`: `)
6572
6654
  _$insertNode(_el$4,_el$5)
6573
6655
  _$setProp(_el$4,"wrapMode","word")
@@ -6575,12 +6657,12 @@ _$insert(_el$4,()=>cancelled()?"Cancelled":"Error",_el$5)
6575
6657
  _$insert(_el$4,()=>props.item.run?.errorMessage,null)
6576
6658
  _$effect((_$p)=>_$setProp(_el$4,"fg",row.focused()?row.foregroundColor():failed()?theme().error:theme().textMuted,_$p))
6577
6659
  return _el$4
6578
- }}),_$createComponent(Show17,{get when(){return props.item.unavailable
6660
+ }}),_$createComponent(Show18,{get when(){return props.item.unavailable
6579
6661
  },get children(){var _el$6=_$createElement("text")
6580
6662
  _$insertNode(_el$6,_$createTextNode(`Worker status unavailable`))
6581
6663
  _$effect((_$p)=>_$setProp(_el$6,"fg",theme().warning,_$p))
6582
6664
  return _el$6
6583
- }}),_$createComponent(Show17,{get when(){return _$memo(()=>props.item.status.type==="retry")()?props.item.status:undefined
6665
+ }}),_$createComponent(Show18,{get when(){return _$memo(()=>props.item.status.type==="retry")()?props.item.status:undefined
6584
6666
  },children:(status)=>(()=>{var _el$0=_$createElement("text"),_el$1=_$createTextNode(`Retry #`),_el$10=_$createTextNode(` \xB7 `),_el$11=_$createTextNode(`s \xB7 `)
6585
6667
  _$insertNode(_el$0,_el$1)
6586
6668
  _$insertNode(_el$0,_el$10)
@@ -6592,7 +6674,7 @@ _$insert(_el$0,()=>status().message,null)
6592
6674
  _$effect((_$p)=>_$setProp(_el$0,"fg",row.focused()?row.foregroundColor():theme().warning,_$p))
6593
6675
  return _el$0
6594
6676
  })()
6595
- }),_$createComponent(Show17,{get when(){return _$memo(()=>!!idle())()&&!props.item.run?.errorMessage
6677
+ }),_$createComponent(Show18,{get when(){return _$memo(()=>!!idle())()&&!props.item.run?.errorMessage
6596
6678
  },get children(){var _el$8=_$createElement("text")
6597
6679
  _$insertNode(_el$8,_$createTextNode(`Finished`))
6598
6680
  _$effect((_$p)=>_$setProp(_el$8,"fg",theme().textMuted,_$p))
@@ -6606,7 +6688,7 @@ function SubagentList(props){return _$createComponent(SidebarRowList,{get densit
6606
6688
  const item=()=>props.itemById(id)??initial
6607
6689
  const startsGroup=()=>index()===0||props.visible[index()-1]?.group!==item().group
6608
6690
  return(()=>{var _el$=_$createElement("box")
6609
- _$insert(_el$,_$createComponent(Show18,{get when(){return startsGroup()
6691
+ _$insert(_el$,_$createComponent(Show19,{get when(){return startsGroup()
6610
6692
  },get children(){var _el$2=_$createElement("text"),_el$3=_$createElement("b")
6611
6693
  _$insertNode(_el$2,_el$3)
6612
6694
  _$insert(_el$3,()=>item().group)
@@ -6634,7 +6716,7 @@ return _$createComponent(Section,{get api(){return props.api
6634
6716
  },sectionId:`${PLUGIN_ID}.section.subagents`,get navigationSection(){return navigationSection()
6635
6717
  },title:"SUBAGENTS",section:"subagents",get summary(){return `${model.list().length} active \xB7 ${model.recent().length} recent`
6636
6718
  },get open(){return props.preferences.expanded().subagents
6637
- },onToggle:()=>props.preferences.toggleSectionExpanded("subagents"),get children(){return [_$createComponent(Show19,{get when(){return model.parentID()
6719
+ },onToggle:()=>props.preferences.toggleSectionExpanded("subagents"),get children(){return [_$createComponent(Show20,{get when(){return model.parentID()
6638
6720
  },children:(id)=>_$createComponent(McpBulkAction,{get api(){return props.api
6639
6721
  },get interaction(){return props.interaction
6640
6722
  },id:`${PLUGIN_ID}.subagents.parent`,get position(){return{section:navigationSection(),row:1,column:0
@@ -6668,7 +6750,7 @@ _$insert(_el$2,_$createComponent(For17,{get each(){return model.tabs()
6668
6750
  },onActivate:()=>model.setMode(value)
6669
6751
  })
6670
6752
  }))
6671
- _$insert(_el$,_$createComponent(Show19,{get when(){return model.filtered().length===0
6753
+ _$insert(_el$,_$createComponent(Show20,{get when(){return model.filtered().length===0
6672
6754
  },get children(){var _el$3=_$createElement("text")
6673
6755
  _$insertNode(_el$3,_$createTextNode(`No matching subagents`))
6674
6756
  _$effect((_$p)=>_$setProp(_el$3,"fg",props.api.theme.current.textMuted,_$p))
@@ -6749,7 +6831,7 @@ _$insert(_el$2,()=>icons.icon(done()?"done":active()?"busy":cancelled()?"close":
6749
6831
  _$setProp(_el$3,"flexGrow",1)
6750
6832
  _$setProp(_el$3,"wrapMode","word")
6751
6833
  _$insert(_el$3,()=>props.item.content)
6752
- _$insert(_el$,_$createComponent(Show20,{get when(){return props.item.priority==="high"||props.item.priority==="medium"||props.item.priority==="low"
6834
+ _$insert(_el$,_$createComponent(Show21,{get when(){return props.item.priority==="high"||props.item.priority==="medium"||props.item.priority==="low"
6753
6835
  },get children(){var _el$4=_$createElement("text"),_el$5=_$createElement("b"),_el$6=_$createTextNode(` `)
6754
6836
  _$insertNode(_el$4,_el$5)
6755
6837
  _$setProp(_el$4,"width",2)
@@ -6785,7 +6867,7 @@ _$insert(_el$2,_$createComponent(For18,{each:["all","active","finished"],childre
6785
6867
  },onActivate:()=>props.setMode(value)
6786
6868
  })
6787
6869
  }))
6788
- _$insert(_el$,_$createComponent(Show21,{get when(){return props.view.rows.length>0
6870
+ _$insert(_el$,_$createComponent(Show22,{get when(){return props.view.rows.length>0
6789
6871
  },get fallback(){return _$createComponent(EmptyTodo,{get api(){return props.api
6790
6872
  },get mode(){return props.mode
6791
6873
  }})
@@ -6793,7 +6875,7 @@ _$insert(_el$,_$createComponent(Show21,{get when(){return props.view.rows.length
6793
6875
  },get children(){return _$createComponent(For18,{get each(){return props.visibility.visible()
6794
6876
  },children:(row,index)=>{const startsGroup=()=>index()===0||props.visibility.visible()[index()-1].group!==row.group
6795
6877
  return(()=>{var _el$3=_$createElement("box")
6796
- _$insert(_el$3,_$createComponent(Show21,{get when(){return startsGroup()
6878
+ _$insert(_el$3,_$createComponent(Show22,{get when(){return startsGroup()
6797
6879
  },get children(){var _el$4=_$createElement("text"),_el$5=_$createElement("b")
6798
6880
  _$insertNode(_el$4,_el$5)
6799
6881
  _$insert(_el$5,()=>row.group)
@@ -6831,7 +6913,7 @@ return _el$6
6831
6913
 
6832
6914
 
6833
6915
  function TodoGuidanceControl(props){const state=()=>props.controller.guidance(props.sessionID)
6834
- return _$createComponent(Show22,{get when(){return state().available
6916
+ return _$createComponent(Show23,{get when(){return state().available
6835
6917
  },get children(){var _el$=_$createElement("box")
6836
6918
  _$insert(_el$,_$createComponent(SectionTab,{get api(){return props.api
6837
6919
  },get interaction(){return props.interaction
@@ -6841,7 +6923,7 @@ _$insert(_el$,_$createComponent(SectionTab,{get api(){return props.api
6841
6923
  },get disabled(){return state().saving
6842
6924
  },onActivate:()=>void props.controller.setGuidance(props.sessionID,!state().enabled)
6843
6925
  }),null)
6844
- _$insert(_el$,_$createComponent(Show22,{get when(){return state().error
6926
+ _$insert(_el$,_$createComponent(Show23,{get when(){return state().error
6845
6927
  },children:(message)=>(()=>{var _el$2=_$createElement("text")
6846
6928
  _$setProp(_el$2,"wrapMode","word")
6847
6929
  _$insert(_el$2,message)
@@ -6852,26 +6934,26 @@ return _el$2
6852
6934
  return _el$
6853
6935
  }})
6854
6936
  }
6855
- function TodoSection(props){const list=createMemo17(()=>props.controller.list(props.sessionID))
6937
+ function TodoSection(props){const list=createMemo18(()=>props.controller.list(props.sessionID))
6856
6938
  const icons=useIcons()
6857
6939
  const unavailable=()=>hostCapabilityUnavailable(props.api,"todo")
6858
6940
  const managed=()=>("guidance" in props.controller)?props.controller:undefined
6859
6941
  const [mode,setMode]=createSignal28("all")
6860
- const targetKey=createMemo17(()=>props.controller.target?.(props.sessionID).key??props.sessionID)
6861
- createEffect15(()=>{targetKey()
6942
+ const targetKey=createMemo18(()=>props.controller.target?.(props.sessionID).key??props.sessionID)
6943
+ createEffect17(()=>{targetKey()
6862
6944
  setMode("all")
6863
6945
  })
6864
- const view=createMemo17(()=>buildTodoView(list(),mode()))
6946
+ const view=createMemo18(()=>buildTodoView(list(),mode()))
6865
6947
  const visibility=createListVisibility({items:()=>view().rows,limit:()=>props.preferences.sectionItemLimit?.("todo")??0,resetKey:()=>JSON.stringify([targetKey(),mode()])
6866
6948
  })
6867
- const state=createMemo17(()=>props.controller.state(props.sessionID))
6868
- createEffect15(()=>{const sessionID=props.sessionID
6949
+ const state=createMemo18(()=>props.controller.state(props.sessionID))
6950
+ createEffect17(()=>{const sessionID=props.sessionID
6869
6951
  targetKey()
6870
6952
  if(unavailable())
6871
6953
  return
6872
- const deactivate=untrack6(()=>props.controller.activate?.(sessionID)??(()=>{}))
6873
- onCleanup20(deactivate)
6874
- untrack6(()=>void props.controller.refresh(sessionID).catch(()=>{}))
6954
+ const deactivate=untrack7(()=>props.controller.activate?.(sessionID)??(()=>{}))
6955
+ onCleanup21(deactivate)
6956
+ untrack7(()=>void props.controller.refresh(sessionID).catch(()=>{}))
6875
6957
  })
6876
6958
  const navigationSection=()=>props.navigationSection??1
6877
6959
  return _$createComponent(Section,{get api(){return props.api
@@ -6879,10 +6961,10 @@ return _$createComponent(Section,{get api(){return props.api
6879
6961
  },sectionId:`${PLUGIN_ID}.section.todo`,get navigationSection(){return navigationSection()
6880
6962
  },title:"TODO",section:"todo",get summary(){return _$memo(()=>!!(unavailable()||managed()?.missing(props.sessionID)))()?"\u2014":`${view().counts.completed}/${list().length}`
6881
6963
  },get open(){return props.preferences.expanded().todo
6882
- },onToggle:()=>props.preferences.toggleSectionExpanded("todo"),get children(){return _$createComponent(Show23,{get when(){return unavailable()
6964
+ },onToggle:()=>props.preferences.toggleSectionExpanded("todo"),get children(){return _$createComponent(Show24,{get when(){return unavailable()
6883
6965
  },get fallback(){return(()=>{var _el$=_$createElement("box")
6884
6966
  _$setProp(_el$,"gap",1)
6885
- _$insert(_el$,_$createComponent(Show23,{get when(){return managed()?.guidance(props.sessionID).available
6967
+ _$insert(_el$,_$createComponent(Show24,{get when(){return managed()?.guidance(props.sessionID).available
6886
6968
  },get children(){return _$createComponent(TodoGuidanceControl,{get api(){return props.api
6887
6969
  },get controller(){return managed()
6888
6970
  },get sessionID(){return props.sessionID
@@ -6890,7 +6972,7 @@ _$insert(_el$,_$createComponent(Show23,{get when(){return managed()?.guidance(pr
6890
6972
  },get navigationSection(){return navigationSection()
6891
6973
  }})
6892
6974
  }}),null)
6893
- _$insert(_el$,_$createComponent(Show23,{get when(){return managed()?.missing(props.sessionID)
6975
+ _$insert(_el$,_$createComponent(Show24,{get when(){return managed()?.missing(props.sessionID)
6894
6976
  },get fallback(){return _$createComponent(SectionRequestBody,{get api(){return props.api
6895
6977
  },get interaction(){return props.interaction
6896
6978
  },id:`${PLUGIN_ID}.retry.todo`,get position(){return{section:navigationSection(),row:1,column:0
@@ -6926,8 +7008,8 @@ return _el$4
6926
7008
  }})
6927
7009
  }
6928
7010
  function SidebarContent(props){const sections=props.preferences.sections
6929
- const visibleSections=createMemo18(()=>props.preferences.sectionOrder().filter((section)=>sections()[section]&&supportsSidebarSection(props.api,section)))
6930
- onCleanup21(()=>props.interaction.setContentRoot(undefined))
7011
+ const visibleSections=createMemo19(()=>props.preferences.sectionOrder().filter((section)=>sections()[section]&&supportsSidebarSection(props.api,section)))
7012
+ onCleanup22(()=>props.interaction.setContentRoot(undefined))
6931
7013
  return(()=>{var _el$=_$createElement("box")
6932
7014
  _$use((node)=>props.interaction.setContentRoot(node),_el$)
6933
7015
  _$setProp(_el$,"id",`${PLUGIN_ID}.root`)
@@ -6973,8 +7055,8 @@ return _el$
6973
7055
  }
6974
7056
 
6975
7057
 
6976
- function McpPersistence(props){const persist=createMemo19(()=>props.controller.persist())
6977
- createEffect16(()=>{if(!props.api.state.ready)
7058
+ function McpPersistence(props){const persist=createMemo20(()=>props.controller.persist())
7059
+ createEffect18(()=>{if(!props.api.state.ready)
6978
7060
  return
6979
7061
  persist()
6980
7062
  const route=props.api.route.current
@@ -6982,20 +7064,20 @@ const params="params" in route?route.params:undefined
6982
7064
  if(typeof params?.sessionID!=="string")
6983
7065
  return
6984
7066
  const current=props.controller.target()
6985
- onCleanup22(()=>props.controller.deactivate(current))
6986
- untrack7(()=>void props.controller.activate(current).catch(()=>{}))
7067
+ onCleanup23(()=>props.controller.deactivate(current))
7068
+ untrack8(()=>void props.controller.activate(current).catch(()=>{}))
6987
7069
  })
6988
7070
  return _$createElement("box")
6989
7071
  }
6990
- function PreferencesPersistence(props){createEffect16(()=>{const location=currentLocation(props.api)
6991
- untrack7(()=>props.controller.setActiveScope(preferencesScope({directory:location.routing.directory,worktree:props.api.state.path.worktree
7072
+ function PreferencesPersistence(props){createEffect18(()=>{const location=currentLocation(props.api)
7073
+ untrack8(()=>props.controller.setActiveScope(preferencesScope({directory:location.routing.directory,worktree:props.api.state.path.worktree
6992
7074
  })))
6993
7075
  props.controller.load()
6994
7076
  })
6995
7077
  return _$createElement("box")
6996
7078
  }
6997
7079
  function FirstRunWizardPersistence(props){let isChecked=false
6998
- createEffect16(()=>{if(isChecked)
7080
+ createEffect18(()=>{if(isChecked)
6999
7081
  return
7000
7082
  isChecked=true
7001
7083
  showFirstRunWizard(props.api,props.preferences).catch(()=>{})
@@ -7013,16 +7095,16 @@ return _$createElement("box")
7013
7095
 
7014
7096
  function SidebarTitle(props){const icons=useIcons()
7015
7097
  const theme=()=>props.api.theme.current
7016
- const created=createMemo20(()=>{const value=props.api.state.session.get(props.sessionID)?.time?.created
7098
+ const created=createMemo21(()=>{const value=props.api.state.session.get(props.sessionID)?.time?.created
7017
7099
  return value===undefined?undefined:`Created ${new Date(value).toLocaleDateString("en", {
7018
7100
  dateStyle: "medium"
7019
7101
  })}`
7020
7102
  })
7021
7103
  const settingsId=`${PLUGIN_ID}.settings`
7022
7104
  const settings=useSidebarItem(props.api,props.interaction,{id:settingsId,position:{section:0,row:0,column:0
7023
- },activate:()=>openSettings(props.api,props.preferences,undefined,props.mcp)
7105
+ },activate:()=>openSettings(props.api,props.preferences,undefined,props.mcp,props.skills)
7024
7106
  },()=>theme().textMuted,"control")
7025
- onCleanup23(()=>props.interaction.setTitleRoot(undefined))
7107
+ onCleanup24(()=>props.interaction.setTitleRoot(undefined))
7026
7108
  return(()=>{var _el$=_$createElement("box"),_el$2=_$createElement("box"),_el$3=_$createElement("box")
7027
7109
  _$insertNode(_el$,_el$2)
7028
7110
  _$use((node)=>props.interaction.setTitleRoot(node),_el$)
@@ -7033,7 +7115,7 @@ _$setProp(_el$2,"flexDirection","row")
7033
7115
  _$setProp(_el$2,"justifyContent","space-between")
7034
7116
  _$setProp(_el$2,"gap",1)
7035
7117
  _$setProp(_el$3,"flexGrow",1)
7036
- _$insert(_el$3,_$createComponent(Show24,{get when(){return props.preferences.showSessionTitle()
7118
+ _$insert(_el$3,_$createComponent(Show25,{get when(){return props.preferences.showSessionTitle()
7037
7119
  },get children(){var _el$4=_$createElement("text"),_el$5=_$createElement("b")
7038
7120
  _$insertNode(_el$4,_el$5)
7039
7121
  _$setProp(_el$4,"wrapMode","word")
@@ -7041,7 +7123,7 @@ _$insert(_el$5,()=>props.title)
7041
7123
  _$effect((_$p)=>_$setProp(_el$4,"fg",theme().text,_$p))
7042
7124
  return _el$4
7043
7125
  }}),null)
7044
- _$insert(_el$3,_$createComponent(Show24,{get when(){return _$memo(()=>!!props.preferences.showSessionDate())()&&created()
7126
+ _$insert(_el$3,_$createComponent(Show25,{get when(){return _$memo(()=>!!props.preferences.showSessionDate())()&&created()
7045
7127
  },children:(value)=>(()=>{var _el$6=_$createElement("text")
7046
7128
  _$insert(_el$6,value)
7047
7129
  _$effect((_$p)=>_$setProp(_el$6,"fg",theme().textMuted,_$p))
@@ -7285,7 +7367,7 @@ function legacyTheme(theme){return{primary:theme.hue.interactive[200],secondary:
7285
7367
 
7286
7368
  function createV2UI(context){let dialogOpen=false
7287
7369
  function DialogPrompt(props){let active=true
7288
- onCleanup24(()=>{active=false
7370
+ onCleanup25(()=>{active=false
7289
7371
  })
7290
7372
  onMount7(async ()=>{const value=await context.ui.dialog.prompt({title:props.title,placeholder:props.placeholder,value:props.value
7291
7373
  })
@@ -7299,7 +7381,7 @@ props.onConfirm?.(value)
7299
7381
  return _$createElement("box")
7300
7382
  }
7301
7383
  function DialogConfirm(props){let active=true
7302
- onCleanup24(()=>{active=false
7384
+ onCleanup25(()=>{active=false
7303
7385
  })
7304
7386
  onMount7(async ()=>{const confirmed=await context.ui.dialog.confirm({title:props.title,message:props.message
7305
7387
  })
@@ -7364,7 +7446,7 @@ context.ui.router.navigate({type:"plugin",name,data:params})
7364
7446
  },attention:context.attention,lifecycle:{signal:controller.signal,onDispose}}
7365
7447
  api.slots=createV2Slots(context,keymap,(dispose)=>{onDispose(dispose)
7366
7448
  })
7367
- setHostCapabilities(api,{todo:true,lsp:false,titleVisibility:false
7449
+ setHostCapabilities(api,{todo:true,lsp:false,titleVisibility:false,permissionMode:false
7368
7450
  })
7369
7451
  return{api,async dispose(){controller.abort()
7370
7452
  for(let index=disposers.length-1;index>=0; index--)
@@ -7459,20 +7541,21 @@ api.lifecycle.onDispose(unsubscribeConnected)
7459
7541
  api.slots.register({order:100,slots:{app(){return _$createComponent(IconProvider,{get style(){return preferences.lspIconStyle
7460
7542
  },get multilineCorners(){return preferences.cornerFont
7461
7543
  },get children(){return [_$createComponent(PreferencesPersistence,{api,controller:preferences
7462
- }),_$createComponent(SettingsBinding,{api,preferences,mcp
7544
+ }),_$memo(()=>_$memo(()=>!!supportsPermissionMode(api))()&&_$createComponent(PermissionModeBinding,{api,preferences
7545
+ })),_$createComponent(SettingsBinding,{api,preferences,mcp,skills
7463
7546
  }),_$createComponent(SidebarToggleBinding,{api,preferences
7464
7547
  }),_$createComponent(SidebarFocusBinding,{api,preferences,interaction
7465
7548
  }),_$createComponent(SearchBinding,{api,preferences,get onNewSession(){return startup.handleNewSession
7466
7549
  },interaction,skills,subagents,mcp
7467
7550
  }),_$createComponent(FirstRunWizardPersistence,{api,preferences
7468
7551
  }),_$createComponent(StartupSessionBinding,{api,controller:startup
7469
- }),_$createComponent(UpgradeNotesBinding,{api,preferences,version:"0.18.2"
7552
+ }),_$createComponent(UpgradeNotesBinding,{api,preferences,version:"0.19.1"
7470
7553
  }),_$createComponent(McpPersistence,{api,controller:mcp
7471
7554
  })]
7472
7555
  }})
7473
7556
  },sidebar_title(_context,props){return _$createComponent(IconProvider,{get style(){return preferences.lspIconStyle
7474
7557
  },get multilineCorners(){return preferences.cornerFont
7475
- },get children(){return _$createComponent(SidebarTitle,{api,preferences,mcp,interaction,get sessionID(){return props.session_id
7558
+ },get children(){return _$createComponent(SidebarTitle,{api,preferences,mcp,skills,interaction,get sessionID(){return props.session_id
7476
7559
  },get title(){return props.title
7477
7560
  }})
7478
7561
  }})
@@ -7483,7 +7566,7 @@ api.slots.register({order:100,slots:{app(){return _$createComponent(IconProvider
7483
7566
  }})
7484
7567
  }})
7485
7568
  }}})
7486
- return{mcp,preferences
7569
+ return{mcp,skills,preferences
7487
7570
  }}
7488
7571
  var setupOpenCodeV1=async (api,options,meta)=>{const{preferences
7489
7572
  }=await setupNavigator(api,options,async ()=>{if(!api.client?.file?.read||!api.state.path.worktree)
@@ -7496,12 +7579,12 @@ throw result.error
7496
7579
  }
7497
7580
  return result.data?.type==="text"?result.data.content:undefined
7498
7581
  })
7499
- const versionStatus=createVersionStatus(api,"0.18.2")
7500
- const versionUpdates=createVersionUpdateActions(api,versionStatus,createOpenCodeV1VersionUpdater(api,meta),()=>preferences.rememberNavigatorVersionBeforeUpdate("0.18.2"))
7582
+ const versionStatus=createVersionStatus(api,"0.19.1")
7583
+ const versionUpdates=createVersionUpdateActions(api,versionStatus,createOpenCodeV1VersionUpdater(api,meta),()=>preferences.rememberNavigatorVersionBeforeUpdate("0.19.1"))
7501
7584
  api.slots.register({order:90,slots:{sidebar_footer(_context,props){return _$createComponent(IconProvider,{get style(){return preferences.lspIconStyle
7502
7585
  },get multilineCorners(){return preferences.cornerFont
7503
7586
  },get children(){return _$createComponent(VersionFooter,{api,get sessionID(){return props.session_id
7504
- },navigatorVersion:"0.18.2",status:versionStatus,get onOpenCodeUpdate(){return versionUpdates.openCode
7587
+ },navigatorVersion:"0.19.1",status:versionStatus,get onOpenCodeUpdate(){return versionUpdates.openCode
7505
7588
  },get onNavigatorUpdate(){return versionUpdates.navigator
7506
7589
  }})
7507
7590
  }})
@@ -7509,25 +7592,25 @@ api.slots.register({order:90,slots:{sidebar_footer(_context,props){return _$crea
7509
7592
  }
7510
7593
  var setupOpenCodeV2=async (context)=>{const adapter=createOpenCodeV2Api(context)
7511
7594
  const todo=createNavigatorTodoController(context,adapter.api)
7512
- const{mcp,preferences
7595
+ const{mcp,skills,preferences
7513
7596
  }=await setupNavigator(adapter.api,context.options,async ()=>{if(!context.client.file?.read)
7514
7597
  return
7515
7598
  return new TextDecoder().decode(await context.client.file.read({location:context.location,path:".opencode/navigator.json"
7516
7599
  }))
7517
7600
  },todo)
7518
- const versionStatus=createVersionStatus(adapter.api,"0.18.2")
7519
- const versionUpdates=createVersionUpdateActions(adapter.api,versionStatus,createOpenCodeV2VersionUpdater(context),()=>preferences.rememberNavigatorVersionBeforeUpdate("0.18.2"))
7601
+ const versionStatus=createVersionStatus(adapter.api,"0.19.1")
7602
+ const versionUpdates=createVersionUpdateActions(adapter.api,versionStatus,createOpenCodeV2VersionUpdater(context),()=>preferences.rememberNavigatorVersionBeforeUpdate("0.19.1"))
7520
7603
  const disposeFooter=context.ui.slot({append:"sidebar.footer",render:()=>_$createComponent(IconProvider,{get style(){return preferences.lspIconStyle
7521
7604
  },get multilineCorners(){return preferences.cornerFont
7522
7605
  },get children(){var _el$=_$createElement("box")
7523
7606
  _$setProp(_el$,"flexDirection","row")
7524
7607
  _$setProp(_el$,"justifyContent","space-between")
7525
7608
  _$insert(_el$,_$createComponent(VersionSummary,{get api(){return adapter.api
7526
- },navigatorVersion:"0.18.2",status:versionStatus,get onOpenCodeUpdate(){return versionUpdates.openCode
7609
+ },navigatorVersion:"0.19.1",status:versionStatus,get onOpenCodeUpdate(){return versionUpdates.openCode
7527
7610
  },get onNavigatorUpdate(){return versionUpdates.navigator
7528
7611
  }}),null)
7529
7612
  _$insert(_el$,_$createComponent(SettingsFooterButton,{get api(){return adapter.api
7530
- },preferences,mcp
7613
+ },preferences,mcp,skills
7531
7614
  }),null)
7532
7615
  return _el$
7533
7616
  }})
@@ -7538,5 +7621,5 @@ await adapter.dispose()
7538
7621
  var plugin={id:PLUGIN_ID,tui:setupOpenCodeV1,setup:setupOpenCodeV2
7539
7622
  }
7540
7623
  var plugin_default=plugin
7541
- export{DEFAULT_SECTION_EXPANSION,FOCUS_COMMAND,FirstRunWizard,KeyboardHelpDialog,LspBadge,McpSection,QUICK_ACTIONS,Section,SectionFilter,SettingsDialog,SidebarFocusBinding,SidebarToggleBinding,SkillsSection,createMcpController,createPreferencesController,createSidebarInteraction,createSkillController,createSubagentController,createTodoController,plugin_default as default,isEffectivelyVisible,lspIcon,matchesFilter,openFirstRunWizard,openKeyboardHelp,openSettings,showFirstRunWizard
7624
+ export{DEFAULT_SECTION_EXPANSION,DialogSurface,FOCUS_COMMAND,FirstRunWizard,KeyboardHelpDialog,LspBadge,McpSection,PresetMenu,QUICK_ACTIONS,Section,SectionFilter,SelectionBox,SettingsDialog,SidebarFocusBinding,SidebarToggleBinding,SkillsSection,createDialogStack,createMcpController,createPreferencesController,createSidebarInteraction,createSkillController,createSubagentController,createTodoController,plugin_default as default,isEffectivelyVisible,lspIcon,matchesFilter,openFirstRunWizard,openKeyboardHelp,openSettings,showFirstRunWizard,useDialogScroll,useDialogState,useDialogs,useIcons
7542
7625
  }