opencode-navigator 0.21.8 → 0.22.0

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,9 +1,9 @@
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"
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,useTerminalDimensions as useTerminalDimensions8,useTerminalDimensions as useTerminalDimensions9} from "@opentui/solid"
2
2
 
3
3
 
4
4
 
5
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,createEffect as createEffect4,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 createEffect5,createSignal as createSignal9,onCleanup as onCleanup4,createSignal as createSignal10,createSignal as createSignal11,Index,createSignal as createSignal12,onCleanup as onCleanup5,createEffect as createEffect7,onCleanup as onCleanup7,batch as batch2,createEffect as createEffect6,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 createEffect8,createSignal as createSignal15,onCleanup as onCleanup9,Show as Show4,For as For6,For as For9,createEffect as createEffect9,createMemo as createMemo5,onCleanup as onCleanup10,createEffect as createEffect10,createMemo as createMemo6,untrack as untrack2,For as For10,createEffect as createEffect11,createMemo as createMemo8,onCleanup as onCleanup11,onMount as onMount4,createMemo as createMemo7,Show as Show6,onCleanup as onCleanup12,createEffect as createEffect12,onCleanup as onCleanup13,createSignal as createSignal16,createMemo as createMemo9,createEffect as createEffect13,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,createSignal as createSignal23,createEffect as createEffect14,createSignal as createSignal22,on,createMemo as createMemo13,createSignal as createSignal26,createMemo as createMemo12,For as For13,Show as Show14,Show as Show11,Show as Show12,createSignal as createSignal24,createContext as createContext3,useContext as useContext3,Show as Show13,createSignal as createSignal25,onCleanup as onCleanup17,Show as Show20,createSignal as createSignal27,untrack as untrack5,createSignal as createSignal28,createSignal as createSignal29,createEffect as createEffect15,For as For15,Show as Show15,For as For14,Show as Show16,Show as Show17,Show as Show18,Show as Show19,For as For16,Show as Show22,createMemo as createMemo15,Show as Show21,createMemo as createMemo14,createSignal as createSignal30,createEffect as createEffect16,onCleanup as onCleanup18,For as For21,Match,Switch,createMemo as createMemo19,onCleanup as onCleanup22,For as For17,Show as Show23,createSignal as createSignal31,createEffect as createEffect17,createMemo as createMemo16,onCleanup as onCleanup19,untrack as untrack6,For as For19,Show as Show26,createEffect as createEffect18,createMemo as createMemo17,createSignal as createSignal32,onCleanup as onCleanup20,untrack as untrack7,For as For18,Show as Show25,Show as Show24,Show as Show30,createEffect as createEffect19,createMemo as createMemo18,createSignal as createSignal33,onCleanup as onCleanup21,untrack as untrack8,For as For20,Show as Show28,Show as Show27,Show as Show29,createEffect as createEffect20,createMemo as createMemo20,onCleanup as onCleanup23,untrack as untrack9,Show as Show31,createMemo as createMemo21,onCleanup as onCleanup24,createEffect as createEffect21,createMemo as createMemo22,on as on2,onCleanup as onCleanup25,createSignal as createSignal34,onCleanup as onCleanup26,onMount as onMount7} from "solid-js"
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,createEffect as createEffect4,Show,splitProps as splitProps3,Suspense,lazy,createSignal as createSignal4,createSignal as createSignal5,onCleanup as onCleanup3,Show as Show2,batch,createSignal as createSignal7,createSignal as createSignal6,createEffect as createEffect5,createSignal as createSignal8,onCleanup as onCleanup4,createSignal as createSignal9,createSignal as createSignal10,Suspense as Suspense2,lazy as lazy2,Index,onCleanup as onCleanup5,createSignal as createSignal11,onCleanup as onCleanup6,createEffect as createEffect7,onCleanup as onCleanup8,batch as batch2,createEffect as createEffect6,createMemo,createSignal as createSignal12,onCleanup as onCleanup7,onMount,For as For2,For as For3,Show as Show3,createMemo as createMemo2,Show as Show4,createSignal as createSignal13,onCleanup as onCleanup9,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 Show6,createEffect as createEffect8,createSignal as createSignal14,onCleanup as onCleanup10,Show as Show5,For as For6,For as For9,createEffect as createEffect9,createMemo as createMemo5,onCleanup as onCleanup11,createEffect as createEffect10,createMemo as createMemo6,untrack as untrack2,Suspense as Suspense3,lazy as lazy3,onCleanup as onCleanup12,createEffect as createEffect11,onCleanup as onCleanup13,createSignal as createSignal15,createMemo as createMemo7,createSignal as createSignal16,lazy as lazy4,Show as Show9,For as For10,Show as Show8,Show as Show7,createEffect as createEffect12,onCleanup as onCleanup14,onMount as onMount4,onCleanup as onCleanup15,onMount as onMount5,For as For11,createSignal as createSignal17,createSignal as createSignal18,Show as Show10,createSignal as createSignal20,createSignal as createSignal19,onCleanup as onCleanup16,For as For12,Show as Show13,createMemo as createMemo9,createComputed,createMemo as createMemo8,createSignal as createSignal21,untrack as untrack3,Show as Show11,createComputed as createComputed2,untrack as untrack4,Show as Show12,createSignal as createSignal23,createEffect as createEffect13,createSignal as createSignal22,on,createMemo as createMemo11,createSignal as createSignal26,createMemo as createMemo10,For as For13,Show as Show17,Show as Show14,Show as Show15,createSignal as createSignal24,createContext as createContext3,useContext as useContext3,Show as Show16,createSignal as createSignal25,onCleanup as onCleanup17,Show as Show23,createSignal as createSignal27,untrack as untrack5,createSignal as createSignal28,createSignal as createSignal29,createEffect as createEffect14,For as For15,Show as Show18,For as For14,Show as Show19,Show as Show20,Show as Show21,Show as Show22,For as For16,Show as Show25,createMemo as createMemo13,Show as Show24,createMemo as createMemo12,createSignal as createSignal30,createContext as createContext4,useContext as useContext4,Show as Show26,Suspense as Suspense4,createEffect as createEffect15,onCleanup as onCleanup18,untrack as untrack6,For as For22,Match,Switch,createMemo as createMemo19,onCleanup as onCleanup24,For as For17,Show as Show27,createMemo as createMemo15,createSignal as createSignal32,createEffect as createEffect16,createMemo as createMemo14,onCleanup as onCleanup19,untrack as untrack7,createEffect as createEffect17,createSignal as createSignal31,onCleanup as onCleanup20,For as For18,Show as Show29,createSignal as createSignal33,createEffect as createEffect18,createMemo as createMemo16,onCleanup as onCleanup21,untrack as untrack8,Show as Show28,For as For20,Show as Show32,createEffect as createEffect19,createMemo as createMemo17,createSignal as createSignal34,onCleanup as onCleanup22,untrack as untrack9,For as For19,Show as Show31,Show as Show30,Show as Show36,createEffect as createEffect20,createMemo as createMemo18,createSignal as createSignal35,onCleanup as onCleanup23,untrack as untrack10,For as For21,Show as Show34,Show as Show33,Show as Show35,createEffect as createEffect21,createMemo as createMemo20,onCleanup as onCleanup25,untrack as untrack11,Show as Show37,createMemo as createMemo21,onCleanup as onCleanup26,createEffect as createEffect22,createMemo as createMemo22,on as on2,onCleanup as onCleanup27,createSignal as createSignal36,onCleanup as onCleanup28,onMount as onMount6} from "solid-js"
7
7
  var SIDEBAR_SECTIONS=["limits","todo","subagents","skills","quick_actions","lsp","mcp"]
8
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"]
9
9
  function preferencesScope(path){return path.worktree||path.directory||"global"
@@ -77,7 +77,7 @@ var FOCUS_COMMAND=`${PLUGIN_ID}.focus`
77
77
  var SEARCH_COMMAND=`${PLUGIN_ID}.search`
78
78
  var DEFAULT_SEARCH_KEY="ctrl+shift+k";
79
79
  function pluginConfig(options){const iconStyle=options?.icon_style==="nerd"||options?.icon_style==="text"?options.icon_style:options?.lsp_icon_style
80
- return{toggleKey:typeof options?.toggle_key==="string"&&options.toggle_key.trim()?options.toggle_key.trim():"ctrl+shift+b",focusKey:typeof options?.focus_key==="string"&&options.focus_key.trim()?options.focus_key.trim():"ctrl+shift+f",searchKey:typeof options?.search_key==="string"&&options.search_key.trim()?options.search_key.trim():DEFAULT_SEARCH_KEY,persistMcp:options?.persist_mcp!==false,limitsRefreshMinutes:parseLimitsRefreshMinutes(options?.limits_refresh_minutes)??DEFAULT_LIMITS_REFRESH_MINUTES,startInChat:options?.start_in_chat===true,showSessionTitle:options?.show_session_title!==false,showSessionDate:options?.show_session_date!==false,cornerFont:options?.corner_font!==false,sections:parseSectionVisibility(options?.sections),sectionOrder:parseSectionOrder(options?.section_order)??[...SIDEBAR_SECTIONS],lspIconStyle:iconStyle==="text"?"text":"nerd",rowDensity:options?.row_density==="comfortable"?"comfortable":"compact",sectionItemLimits:parseSectionItemLimits(options?.section_item_limits),quickActionOrder:parseQuickActionOrder(options?.quick_action_order)??[...QUICK_ACTION_IDS],quickActionVisibility:parseQuickActionVisibility(options?.quick_action_visibility)
80
+ return{toggleKey:typeof options?.toggle_key==="string"&&options.toggle_key.trim()?options.toggle_key.trim():"ctrl+shift+b",focusKey:typeof options?.focus_key==="string"&&options.focus_key.trim()?options.focus_key.trim():"ctrl+shift+f",searchKey:typeof options?.search_key==="string"&&options.search_key.trim()?options.search_key.trim():DEFAULT_SEARCH_KEY,persistMcp:options?.persist_mcp!==false,limitsRefreshMinutes:parseLimitsRefreshMinutes(options?.limits_refresh_minutes)??DEFAULT_LIMITS_REFRESH_MINUTES,startInChat:options?.start_in_chat===true,showSessionTitle:options?.show_session_title!==false,showSessionDate:options?.show_session_date!==false,cornerFont:options?.corner_font!==false,sections:parseSectionVisibility(options?.sections),sectionOrder:parseSectionOrder(options?.section_order)??[...SIDEBAR_SECTIONS],lspIconStyle:iconStyle==="text"?"text":"nerd",rowDensity:options?.row_density==="comfortable"?"comfortable":"compact",toolbarOverflow:options?.toolbar_overflow==="wrap"?"wrap":"menu",sectionItemLimits:parseSectionItemLimits(options?.section_item_limits),quickActionOrder:parseQuickActionOrder(options?.quick_action_order)??[...QUICK_ACTION_IDS],quickActionVisibility:parseQuickActionVisibility(options?.quick_action_visibility)
81
81
  }}
82
82
  function currentLocation(api){const route=api.route.current
83
83
  const params="params" in route?route.params:undefined
@@ -724,8 +724,13 @@ setPosition(body.scrollTop)
724
724
 
725
725
 
726
726
 
727
- import {RGBA,TextAttributes,TextAttributes as TextAttributes2,TextAttributes as TextAttributes3,RGBA as RGBA2,parseColor,TextAttributes as TextAttributes6,TextAttributes as TextAttributes4,TextAttributes as TextAttributes5,TextAttributes as TextAttributes7,RGBA as RGBA3,parseColor as parseColor2,TextAttributes as TextAttributes8,TextAttributes as TextAttributes9,TextAttributes as TextAttributes12,TextAttributes as TextAttributes10,TextAttributes as TextAttributes11,TextAttributes as TextAttributes13,TextAttributes as TextAttributes14,TextAttributes as TextAttributes16,TextAttributes as TextAttributes15,TextAttributes as TextAttributes17,ScrollBoxRenderable,TextAttributes as TextAttributes18} from "@opentui/core"
727
+ import {BoxRenderable,RGBA,TextAttributes,TextAttributes as TextAttributes2,TextAttributes as TextAttributes3,RGBA as RGBA2,parseColor,TextAttributes as TextAttributes4,TextAttributes as TextAttributes5,TextAttributes as TextAttributes6,TextAttributes as TextAttributes7,RGBA as RGBA3,parseColor as parseColor2,TextAttributes as TextAttributes8,TextAttributes as TextAttributes9,TextAttributes as TextAttributes12,TextAttributes as TextAttributes10,TextAttributes as TextAttributes11,TextAttributes as TextAttributes13,TextAttributes as TextAttributes14,TextAttributes as TextAttributes16,TextAttributes as TextAttributes15,TextAttributes as TextAttributes17,ScrollBoxRenderable,TextAttributes as TextAttributes18} from "@opentui/core"
728
728
 
729
+ function selectionBackdrop(node){for(let parent=node.parent;parent; parent=parent.parent){if(parent instanceof BoxRenderable&&parent.backgroundColor.a>0)
730
+ return parent.backgroundColor
731
+ }
732
+ return RGBA.fromValues(0,0,0,1)
733
+ }
729
734
  function SelectionBox(props){const icons=useIcons()
730
735
  const [local,boxProps]=splitProps(props,["ref","iconOnly"])
731
736
  let node
@@ -743,11 +748,9 @@ const right=left + this.width-1
743
748
  const top=this.screenY
744
749
  const bottom=top + this.height-1
745
750
  const positions=this.height===1?[[left,top,"selectionLeft"],[right,top,"selectionRight"]]:[[left,top,"selectionTopLeft"],[right,top,"selectionTopRight"],[left,bottom,"selectionBottomLeft"],[right,bottom,"selectionBottomRight"]]
746
- const background=buffer.buffers.bg
751
+ const backdrop=selectionBackdrop(this)
747
752
  for(const [x,y,icon] of positions){if(x<0||y<0||x>=buffer.width||y>=buffer.height)
748
753
  continue
749
- const offset=(y*buffer.width + x)*4
750
- const backdrop=new RGBA(background.slice(offset,offset + 4))
751
754
  if(!this.backgroundColor.equals(backdrop))
752
755
  corners.push({x,y,icon,backdrop
753
756
  })
@@ -921,9 +924,11 @@ return _el$
921
924
 
922
925
 
923
926
 
927
+
924
928
  function SelectionMenu(props){const icons=useIcons()
925
929
  const dialogs=useDialogs(props.api)
926
930
  const scroll=useDialogScroll()
931
+ const dimensions=useTerminalDimensions2()
927
932
  const [active,setActive]=useDialogState("selection",0)
928
933
  const theme=()=>props.api.theme.current
929
934
  let body
@@ -948,6 +953,7 @@ const unregister=props.api.keymap.registerLayer({mode:"modal",priority:1000,comm
948
953
  })
949
954
  onCleanup2(unregister)
950
955
  return _$createComponent(DialogSurface,{get api(){return props.api
956
+ },get lift(){return props.lift
951
957
  },get children(){return [(()=>{var _el$=_$createElement("box"),_el$2=_$createElement("text"),_el$3=_$createTextNode(` `),_el$4=_$createElement("text")
952
958
  _$insertNode(_el$,_el$2)
953
959
  _$insertNode(_el$,_el$4)
@@ -1000,7 +1006,7 @@ return _el$10
1000
1006
  })()]
1001
1007
  }})
1002
1008
  }))
1003
- _$effect((_p$)=>{var{restore:_v$5,save:_v$6}=scroll,_v$7=props.height??Math.min(props.options.length*3,15)
1009
+ _$effect((_p$)=>{var{restore:_v$5,save:_v$6}=scroll,_v$7=props.adaptive?Math.min(props.height??Math.min(props.options.length*3,15),Math.max(2,Math.floor(dimensions().height*0.75)-8)):props.height??Math.min(props.options.length*3,15)
1004
1010
  _v$5!==_p$.e&&(_p$.e=_$setProp(_el$5,"renderBefore",_v$5,_p$.e))
1005
1011
  _v$6!==_p$.t&&(_p$.t=_$setProp(_el$5,"renderAfter",_v$6,_p$.t))
1006
1012
  _v$7!==_p$.a&&(_p$.a=_$setProp(_el$5,"height",_v$7,_p$.a))
@@ -1085,6 +1091,27 @@ function subtleLineColor(background,border){const from=parseColor(background)
1085
1091
  const to=parseColor(border)
1086
1092
  return RGBA2.fromValues(from.r + (to.r-from.r)*0.45,from.g + (to.g-from.g)*0.45,from.b + (to.b-from.b)*0.45)
1087
1093
  }
1094
+
1095
+
1096
+
1097
+
1098
+ var PickerComponent=lazy(async ()=>{const path=import.meta.url.includes("/dist/tui.js")?"./icon-picker.js":"./icon-picker/icon-picker"
1099
+ const module=await import(path)
1100
+ return{default:module.IconPicker
1101
+ }})
1102
+ function IconPicker(props){return(()=>{var _el$=_$createElement("box")
1103
+ _$insert(_el$,_$createComponent(Suspense,{get children(){return _$createComponent(PickerComponent,props)
1104
+ }}))
1105
+ return _el$
1106
+ })()
1107
+ }
1108
+ var glyphs={plus:["\uEA60","+"],check:["\uEAB2","v"],circle:["\uEAEE","o"],star:["\uEA6A","*"],pin:["\uEBAB","^"],bolt:["\uEA86","!"],book:["\uEAA4","B"],search:["\uEA6D","?"],code:["\uEAC4","#"],terminal:["\uEA85",">"],gear:["\uEB51","G"],shield:["\uEBB3","S"],lock:["\uEA75","L"],unlock:["\uEB74","U"],eye:["\uEA70","E"],clock:["\uEA82","T"],refresh:["\uEAF5","R"],history:["\uEA82","H"],copy:["\uEBCC","C"],export:["\uEBAC","X"],edit:["\uEA73","/"],fork:["\uEB9E","F"],list:["\uEBEB","="],play:["\uEB2C",">"],pause:["\uEAD1","|"],stop:["\uEAD7","s"],rocket:["\uEB44","r"],bug:["\uEAAF","b"],beaker:["\uEA79","t"],wand:["\uEAB6","w"],cloud:["\uEABA","c"],server:["\uEB50","s"],folder:["\uEA83","D"],file:["\uEA7B","f"],heart:["\uEB05","h"],lightbulb:["\uEA61","i"],"arrow-up":["\uEAA1","^"],"arrow-down":["\uEA9A","v"],warning:["\uEA6C","!"],close:["\uEA76","x"]
1109
+ }
1110
+ var terminalIconIDs=Object.keys(glyphs)
1111
+ function terminalIcon(id,style){return(glyphs[id]??glyphs.bolt)[style==="nerd"?0:1]
1112
+ }
1113
+ function terminalIconLabel(id){return id.replaceAll("-"," ")
1114
+ }
1088
1115
  function McpErrorDialog(props){return _$createComponent(SelectionMenu,{get api(){return props.api
1089
1116
  },get title(){return `MCP error \xB7 ${props.name}`
1090
1117
  },height:12,get options(){return [{title:`Status \xB7 ${props.status}`,value:"error",description:props.error,icon:"error"
@@ -1192,22 +1219,95 @@ throw new Error(`Expected format ${PORTABLE_SETTINGS_FORMAT}`)
1192
1219
  if(input.version!==1)
1193
1220
  throw new Error(`Unsupported settings version ${String(input.version)}`)
1194
1221
  const unsupported=[]
1195
- unknownKeys(input,["format","version","layout","mcp"],"",unsupported)
1222
+ unknownKeys(input,["format","version","layout","mcp","behavior"],"",unsupported)
1196
1223
  const hasLayout=Object.hasOwn(input,"layout")
1197
1224
  const hasMcp=Object.hasOwn(input,"mcp")
1198
- if(!hasLayout&&!hasMcp)
1225
+ const behavior={}
1226
+ if(input.behavior!==undefined){const raw=object(input.behavior,"/behavior")
1227
+ unknownKeys(raw,["toolbarOverflow"],"/behavior",unsupported)
1228
+ if(raw.toolbarOverflow!==undefined){if(raw.toolbarOverflow!=="menu"&&raw.toolbarOverflow!=="wrap")
1229
+ throw new Error("/behavior/toolbarOverflow must be menu or wrap")
1230
+ behavior.toolbarOverflow=raw.toolbarOverflow
1231
+ }}
1232
+ if(!hasLayout&&!hasMcp&&!behavior.toolbarOverflow)
1199
1233
  throw new Error("Settings JSON contains no supported settings")
1200
- const settings={format:PORTABLE_SETTINGS_FORMAT,version:1,...hasLayout&&{layout:parseLayout(input.layout,unsupported)},...hasMcp&&{mcp:parseMcp(input.mcp)}}
1234
+ const settings={format:PORTABLE_SETTINGS_FORMAT,version:1,...hasLayout&&{layout:parseLayout(input.layout,unsupported)},...hasMcp&&{mcp:parseMcp(input.mcp)},...behavior.toolbarOverflow&&{behavior}}
1201
1235
  unsupported.sort()
1202
1236
  return{settings,unsupported}}
1203
- function serializePortableSettings(layout,mcp){return `${JSON.stringify({
1237
+ function serializePortableSettings(layout,mcp,behavior){return `${JSON.stringify({
1204
1238
  format: PORTABLE_SETTINGS_FORMAT,
1205
1239
  version: 1,
1206
1240
  layout,
1241
+ ...behavior && { behavior },
1207
1242
  mcp: Object.fromEntries(Object.entries(mcp).sort(([left], [right]) => left.localeCompare(right)))
1208
1243
  }, undefined, 2)}
1209
1244
  `
1210
1245
  }
1246
+ function toolbarPinKey(pin){return pin.kind==="action"?`action:${pin.id}`:`skill:${pin.location}`
1247
+ }
1248
+ function identifier(value){return typeof value==="string"&&/^[a-z][a-z\d-]{0,47}$/u.test(value)
1249
+ }
1250
+ function parsePin(value){if(!value||typeof value!=="object")
1251
+ return
1252
+ const input=value
1253
+ if(!identifier(input.icon))
1254
+ return
1255
+ const stateIcons=Object.fromEntries(Object.entries(input.stateIcons&&typeof input.stateIcons==="object"?input.stateIcons:{}).filter(([key,icon])=>identifier(key)&&identifier(icon)))
1256
+ const icons={icon:input.icon,...Object.keys(stateIcons).length>0&&{stateIcons}}
1257
+ if(input.kind==="action"&&QUICK_ACTION_IDS.includes(input.id))
1258
+ return{kind:"action",id:input.id,...icons}
1259
+ if(input.kind==="skill"&&typeof input.location==="string"&&input.location.trim()&&typeof input.name==="string"&&input.name.trim())
1260
+ return{kind:"skill",location:input.location,name:input.name.trim().slice(0,128),...icons}
1261
+ return
1262
+ }
1263
+ function parseToolbarPins(value){if(!Array.isArray(value))
1264
+ return []
1265
+ const keys=new Set
1266
+ return value.flatMap((candidate)=>{const pin=parsePin(candidate)
1267
+ if(!pin||keys.has(toolbarPinKey(pin))||keys.size>=100)
1268
+ return []
1269
+ keys.add(toolbarPinKey(pin))
1270
+ return [pin]
1271
+ })
1272
+ }
1273
+ function changeToolbarPins(current=[],change){const pins=parseToolbarPins(current)
1274
+ if(change.operation==="pin"){const pin=parsePin(change.pin)
1275
+ if(!pin)
1276
+ throw new Error("Invalid toolbar pin")
1277
+ if(pins.some((item)=>toolbarPinKey(item)===toolbarPinKey(pin)))
1278
+ throw new Error("This item is already pinned")
1279
+ if(pins.length>=100)
1280
+ throw new Error("You can pin at most 100 items")
1281
+ return [...pins,pin]
1282
+ }
1283
+ const index=pins.findIndex((pin)=>toolbarPinKey(pin)===change.key)
1284
+ if(index===-1){if(change.operation==="configure")
1285
+ throw new Error("Pin no longer exists; reopen the toolbar manager")
1286
+ return pins
1287
+ }
1288
+ if(change.operation==="configure"){if(change.expected&&change.expected!==JSON.stringify(pins[index]))
1289
+ throw new Error("Pin changed; reopen its configuration")
1290
+ const stateIcons={...pins[index].stateIcons}
1291
+ const changes=Object.entries(change.stateIcons??{})
1292
+ for(const [state,icon] of changes){if(!identifier(state)||icon!==null&&!identifier(icon))
1293
+ throw new Error("Invalid state icon")
1294
+ if(icon===null)
1295
+ delete stateIcons[state]
1296
+ else
1297
+ stateIcons[state]=icon
1298
+ }
1299
+ const pin=parsePin({...pins[index],icon:change.icon,stateIcons})
1300
+ if(!pin)
1301
+ throw new Error("Invalid toolbar icon")
1302
+ pins[index]=pin
1303
+ return pins
1304
+ }
1305
+ const [pin]=pins.splice(index,1)
1306
+ if(change.operation==="move"){const destination=pins.findIndex((item)=>toolbarPinKey(item)===change.before)
1307
+ pins.splice(destination===-1?pins.length:destination,0,pin)
1308
+ }
1309
+ return pins
1310
+ }
1211
1311
  function record(value){if(!value||typeof value!=="object"||Array.isArray(value))
1212
1312
  return
1213
1313
  return value
@@ -1216,7 +1316,8 @@ function parsePluginSettings(value){const input=record(value)
1216
1316
  if(!input)
1217
1317
  return{}
1218
1318
  return{...typeof input.toggleKey==="string"&&input.toggleKey.trim()&&{toggleKey:input.toggleKey.trim()},...typeof input.focusKey==="string"&&input.focusKey.trim()&&{focusKey:input.focusKey.trim()},...typeof input.searchKey==="string"&&input.searchKey.trim()&&{searchKey:input.searchKey.trim()},...typeof input.persistMcp==="boolean"&&{persistMcp:input.persistMcp},...parseLimitsRefreshMinutes(input.limitsRefreshMinutes)!==undefined&&{limitsRefreshMinutes:parseLimitsRefreshMinutes(input.limitsRefreshMinutes)
1219
- },...typeof input.startInChat==="boolean"&&{startInChat:input.startInChat},...typeof input.showSessionTitle==="boolean"&&{showSessionTitle:input.showSessionTitle},...typeof input.showSessionDate==="boolean"&&{showSessionDate:input.showSessionDate},...typeof input.cornerFont==="boolean"&&{cornerFont:input.cornerFont},...(input.lspIconStyle==="nerd"||input.lspIconStyle==="text")&&{lspIconStyle:input.lspIconStyle},...(input.rowDensity==="compact"||input.rowDensity==="comfortable")&&{rowDensity:input.rowDensity
1319
+ },...typeof input.startInChat==="boolean"&&{startInChat:input.startInChat},...(input.toolbarOverflow==="menu"||input.toolbarOverflow==="wrap")&&{toolbarOverflow:input.toolbarOverflow
1320
+ },...typeof input.showSessionTitle==="boolean"&&{showSessionTitle:input.showSessionTitle},...typeof input.showSessionDate==="boolean"&&{showSessionDate:input.showSessionDate},...typeof input.cornerFont==="boolean"&&{cornerFont:input.cornerFont},...(input.lspIconStyle==="nerd"||input.lspIconStyle==="text")&&{lspIconStyle:input.lspIconStyle},...(input.rowDensity==="compact"||input.rowDensity==="comfortable")&&{rowDensity:input.rowDensity
1220
1321
  },...Object.keys(parseSectionItemLimits(input.sectionItemLimits)).length>0&&{sectionItemLimits:parseSectionItemLimits(input.sectionItemLimits)
1221
1322
  },...parseQuickActionOrder(input.quickActionOrder)&&{quickActionOrder:parseQuickActionOrder(input.quickActionOrder)
1222
1323
  },...Object.keys(parseQuickActionVisibility(input.quickActionVisibility)).length>0&&{quickActionVisibility:parseQuickActionVisibility(input.quickActionVisibility)
@@ -1322,7 +1423,8 @@ return{global:{...Object.keys(behavior).length>0&&{behavior},...layout&&{layout}
1322
1423
  },...typeof userInput?.lastNavigatorVersion==="string"&&{lastNavigatorVersion:userInput.lastNavigatorVersion
1323
1424
  },...typeof userInput?.previousNavigatorVersion==="string"&&{previousNavigatorVersion:userInput.previousNavigatorVersion
1324
1425
  },...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},...Object.keys(codexAccountBindings).length>0&&{codexAccountBindings},...pendingResetAttempt&&{pendingResetAttempt},...typeof userInput?.autoApprovePermissions==="boolean"&&{autoApprovePermissions:userInput.autoApprovePermissions
1325
- },...Object.keys(workspaceProfiles).length>0&&{workspaceProfiles}}}}
1426
+ },...Object.keys(workspaceProfiles).length>0&&{workspaceProfiles},...parseToolbarPins(userInput?.toolbarPins).length>0&&{toolbarPins:parseToolbarPins(userInput?.toolbarPins)
1427
+ }}}}
1326
1428
  function parseValues(value){if(!value)
1327
1429
  return{}
1328
1430
  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)
@@ -1369,7 +1471,7 @@ delete profiles[layout]
1369
1471
  }}
1370
1472
  function applyPreferencesUpdate(current,update){const target=update.target??(update.mcp?.scope?targetForLegacyScope(update.mcp.scope):{kind:"global"})
1371
1473
  const existing=targetPreferences(current,target)
1372
- if(update.expectedScope&&update.expectedScope!==JSON.stringify({layout:existing.layout,mcp:existing.mcp})){throw new Error("Settings changed after this preview; reopen the import preview")
1474
+ if(update.expectedScope&&update.expectedScope!==JSON.stringify({layout:existing.layout,mcp:existing.mcp,behavior:existing.behavior})){throw new Error("Settings changed after this preview; reopen the import preview")
1373
1475
  }
1374
1476
  const behavior={...!update.clearBehavior&&existing.behavior,...parsePluginSettings(update.behavior)
1375
1477
  }
@@ -1489,8 +1591,9 @@ favoriteSkills.splice(index,1)
1489
1591
  favoriteSkills.sort()
1490
1592
  }
1491
1593
  const onboardingCompleted=typeof update.user?.onboardingCompleted==="boolean"?update.user.onboardingCompleted:current.user.onboardingCompleted
1594
+ const toolbarPins=update.user?.toolbarPin?changeToolbarPins(current.user.toolbarPins,update.user.toolbarPin):current.user.toolbarPins
1492
1595
  return{global:target.kind==="global"?scope:current.global,worktrees,user:{...skippedSkillConfirmations.size>0&&{skippedSkillConfirmations:[...skippedSkillConfirmations].sort()
1493
- },...typeof onboardingCompleted==="boolean"&&{onboardingCompleted},...(update.user?.lastNavigatorVersion??current.user.lastNavigatorVersion)&&{lastNavigatorVersion:update.user?.lastNavigatorVersion??current.user.lastNavigatorVersion
1596
+ },...typeof onboardingCompleted==="boolean"&&{onboardingCompleted},...toolbarPins?.length&&{toolbarPins},...(update.user?.lastNavigatorVersion??current.user.lastNavigatorVersion)&&{lastNavigatorVersion:update.user?.lastNavigatorVersion??current.user.lastNavigatorVersion
1494
1597
  },...(update.user?.previousNavigatorVersion??current.user.previousNavigatorVersion)&&{previousNavigatorVersion:update.user?.previousNavigatorVersion??current.user.previousNavigatorVersion
1495
1598
  },...Object.keys(parsedLayoutPresets).length>0&&{layoutPresets:parsedLayoutPresets},...Object.keys(parsedMcpPresets).length>0&&{mcpPresets:parsedMcpPresets},...Object.keys(workspaceProfiles).length>0&&{workspaceProfiles:parseWorkspaceProfiles(workspaceProfiles)
1496
1599
  },...favoriteSkills.length>0&&{favoriteSkills},...favoriteMcpServers.size>0&&{favoriteMcpServers:[...favoriteMcpServers].sort()},...favoriteQuickActions.size>0&&{favoriteQuickActions:parseFavoriteQuickActions([...favoriteQuickActions])
@@ -1648,7 +1751,7 @@ return{behavior:scope.behavior,layout:scope.layout,desiredMcpStates:scope.mcp
1648
1751
  }}
1649
1752
  function mergeSessionLayout(base,session){const order=session.order??base?.order
1650
1753
  return{sections:{...base?.sections,...session.sections},expanded:{...base?.expanded,...session.expanded},...order&&{order:[...order]}}}
1651
- function createPreferencesController(api,defaults,store,configured={}){const builtIns={behavior:{toggleKey:defaults.toggleKey,focusKey:defaults.focusKey,searchKey:defaults.searchKey,persistMcp:defaults.persistMcp,limitsRefreshMinutes:defaults.limitsRefreshMinutes,startInChat:defaults.startInChat,showSessionTitle:defaults.showSessionTitle,showSessionDate:defaults.showSessionDate,cornerFont:defaults.cornerFont,lspIconStyle:defaults.lspIconStyle,rowDensity:defaults.rowDensity,sectionItemLimits:defaults.sectionItemLimits,quickActionOrder:defaults.quickActionOrder,quickActionVisibility:defaults.quickActionVisibility
1754
+ function createPreferencesController(api,defaults,store,configured={}){const builtIns={behavior:{toggleKey:defaults.toggleKey,focusKey:defaults.focusKey,searchKey:defaults.searchKey,persistMcp:defaults.persistMcp,limitsRefreshMinutes:defaults.limitsRefreshMinutes,startInChat:defaults.startInChat,showSessionTitle:defaults.showSessionTitle,showSessionDate:defaults.showSessionDate,cornerFont:defaults.cornerFont,lspIconStyle:defaults.lspIconStyle,rowDensity:defaults.rowDensity,toolbarOverflow:defaults.toolbarOverflow,sectionItemLimits:defaults.sectionItemLimits,quickActionOrder:defaults.quickActionOrder,quickActionVisibility:defaults.quickActionVisibility
1652
1755
  },layout:{sections:defaults.sections,expanded:DEFAULT_SECTION_EXPANSION,order:defaults.sectionOrder??[...SIDEBAR_SECTIONS]
1653
1756
  },desiredMcpStates:{}}
1654
1757
  const [resolved,setResolved]=createSignal4(resolvePreferences({builtIns,pluginOptions:configured}))
@@ -1714,7 +1817,7 @@ return resolveTarget(selectedTarget())
1714
1817
  function workspaceProfiles(){revision()
1715
1818
  return{...configured.workspaceProfiles,...document.user.workspaceProfiles}}
1716
1819
  function scopeSnapshot(target=selectedTarget()){const scope=target.kind==="global"?document.global:document.worktrees[target.key]
1717
- return JSON.stringify({layout:scope?.layout,mcp:scope?.mcp})
1820
+ return JSON.stringify({layout:scope?.layout,mcp:scope?.mcp,behavior:scope?.behavior})
1718
1821
  }
1719
1822
  function update(change){updateRevision++
1720
1823
  document=applyPreferencesUpdate(document,change)
@@ -1891,9 +1994,15 @@ next.add(id)
1891
1994
  setFavoriteQuickActions(next)
1892
1995
  update({user:{favoriteQuickAction:{id,favorite:next.has(id)}}})
1893
1996
  }
1894
- return{sections:()=>resolved().layout.sections,expanded:()=>resolved().layout.expanded,sectionOrder:()=>resolved().layout.order,toggleKey:()=>resolved().behavior.toggleKey,focusKey:()=>resolved().behavior.focusKey,searchKey:()=>resolved().behavior.searchKey,persistMcp:()=>resolved().behavior.persistMcp,limitsRefreshMinutes:()=>resolved().behavior.limitsRefreshMinutes,showSessionTitle:()=>resolved().behavior.showSessionTitle,showSessionDate:()=>resolved().behavior.showSessionDate,startInChatForScope:(scope)=>{revision()
1997
+ return{sections:()=>resolved().layout.sections,toolbarPins(){revision()
1998
+ return document.user.toolbarPins??[]
1999
+ },changeToolbarPin(change){requireHydration()
2000
+ update({user:{toolbarPin:change}})
2001
+ },expanded:()=>resolved().layout.expanded,sectionOrder:()=>resolved().layout.order,toggleKey:()=>resolved().behavior.toggleKey,focusKey:()=>resolved().behavior.focusKey,searchKey:()=>resolved().behavior.searchKey,persistMcp:()=>resolved().behavior.persistMcp,limitsRefreshMinutes:()=>resolved().behavior.limitsRefreshMinutes,showSessionTitle:()=>resolved().behavior.showSessionTitle,showSessionDate:()=>resolved().behavior.showSessionDate,startInChatForScope:(scope)=>{revision()
1895
2002
  return resolveTarget(targetForScope(scope),false).behavior.startInChat
1896
- },cornerFont:()=>resolved().behavior.cornerFont,lspIconStyle:()=>resolved().behavior.lspIconStyle,rowDensity:()=>resolved().behavior.rowDensity,selectedToggleKey:()=>selectedResolved().behavior.toggleKey,selectedFocusKey:()=>selectedResolved().behavior.focusKey,selectedSearchKey:()=>selectedResolved().behavior.searchKey,selectedPersistMcp:()=>selectedResolved().behavior.persistMcp,selectedLimitsRefreshMinutes:()=>selectedResolved().behavior.limitsRefreshMinutes,setLimitsRefreshMinutes(value){if(parseLimitsRefreshMinutes(value)===undefined)
2003
+ },cornerFont:()=>resolved().behavior.cornerFont,lspIconStyle:()=>resolved().behavior.lspIconStyle,rowDensity:()=>resolved().behavior.rowDensity,toolbarOverflow:()=>resolved().behavior.toolbarOverflow,selectedToolbarOverflow:()=>selectedResolved().behavior.toolbarOverflow,toggleToolbarOverflow(){load()
2004
+ update({target:selectedTarget(),behavior:{toolbarOverflow:selectedResolved().behavior.toolbarOverflow==="menu"?"wrap":"menu"}})
2005
+ },selectedToggleKey:()=>selectedResolved().behavior.toggleKey,selectedFocusKey:()=>selectedResolved().behavior.focusKey,selectedSearchKey:()=>selectedResolved().behavior.searchKey,selectedPersistMcp:()=>selectedResolved().behavior.persistMcp,selectedLimitsRefreshMinutes:()=>selectedResolved().behavior.limitsRefreshMinutes,setLimitsRefreshMinutes(value){if(parseLimitsRefreshMinutes(value)===undefined)
1897
2006
  throw new Error("Enter whole minutes (at least 1 minute, within the supported timer range)")
1898
2007
  load()
1899
2008
  update({target:selectedTarget(),behavior:{limitsRefreshMinutes:value}})
@@ -1911,23 +2020,24 @@ update({target:selectedTarget(),behavior:{quickActionOrder:order}})
1911
2020
  throw new Error("Enter a non-negative whole number (0 for All)")
1912
2021
  load()
1913
2022
  update({target:selectedTarget(),behavior:{sectionItemLimits:{[section]:value}}})
1914
- },selectedSections:()=>selectedLayoutResolved().layout.sections,selectedExpanded:()=>selectedLayoutResolved().layout.expanded,selectedSectionOrder:()=>selectedLayoutResolved().layout.order,layoutPresets,mcpPresets,workspaceProfiles,exportPortableSettings(){return serializePortableSettings(selectedLayoutResolved().layout,selectedResolved().desiredMcpStates)
2023
+ },selectedSections:()=>selectedLayoutResolved().layout.sections,selectedExpanded:()=>selectedLayoutResolved().layout.expanded,selectedSectionOrder:()=>selectedLayoutResolved().layout.order,layoutPresets,mcpPresets,workspaceProfiles,exportPortableSettings(){return serializePortableSettings(selectedLayoutResolved().layout,selectedResolved().desiredMcpStates,{toolbarOverflow:selectedResolved().behavior.toolbarOverflow
2024
+ })
1915
2025
  },previewPortableSettings(source){requireHydration()
1916
2026
  const parsed=parsePortableSettings(source)
1917
2027
  const target=selectedTarget()
1918
2028
  const current=selectedResolved()
1919
2029
  const scope=target.kind==="global"?document.global:document.worktrees[target.key]??{}
1920
- const imported={...scope,...parsed.settings.layout&&{layout:parsed.settings.layout},...parsed.settings.mcp&&{mcp:parsed.settings.mcp}}
2030
+ const imported={...scope,...parsed.settings.behavior&&{behavior:{...scope.behavior,...parsed.settings.behavior}},...parsed.settings.layout&&{layout:parsed.settings.layout},...parsed.settings.mcp&&{mcp:parsed.settings.mcp}}
1921
2031
  const next=resolvePreferences({builtIns,pluginOptions:configured,global:values(target.kind==="global"?imported:document.global),worktree:target.kind==="worktree"?values(imported):undefined
1922
2032
  })
1923
2033
  const layoutChanged=Boolean(parsed.settings.layout&&JSON.stringify(next.layout)!==JSON.stringify(selectedLayoutResolved().layout))
1924
2034
  const mcpChanged=Boolean(parsed.settings.mcp&&JSON.stringify(next.desiredMcpStates)!==JSON.stringify(current.desiredMcpStates))
1925
- return{...parsed,target:targetKey(target),expectedScope:scopeSnapshot(target),layoutChanged,mcpChanged
2035
+ return{...parsed,target:targetKey(target),expectedScope:scopeSnapshot(target),layoutChanged,mcpChanged,behaviorChanged:Boolean(parsed.settings.behavior&&next.behavior.toolbarOverflow!==current.behavior.toolbarOverflow)
1926
2036
  }},async applyPortableSettings(preview){await load()
1927
2037
  const target=selectedTarget()
1928
2038
  if(preview.target!==targetKey(target))
1929
2039
  throw new Error("Preference scope changed; reopen the import preview")
1930
- 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}}
2040
+ const change={target,expectedScope:preview.expectedScope,...preview.settings.behavior&&{behavior:preview.settings.behavior},...preview.settings.layout&&{layout:preview.settings.layout,clearLayout:true},...preview.settings.mcp&&{mcp:{states:preview.settings.mcp},clearMcp:true}}
1931
2041
  updateRevision++
1932
2042
  await store.update(change)
1933
2043
  document=await store.load()
@@ -2179,6 +2289,7 @@ const targets=new Map
2179
2289
  const requests=createRequestState(api.lifecycle.signal)
2180
2290
  const promptRequests=createRequestState(api.lifecycle.signal)
2181
2291
  let activeTarget
2292
+ let leases=new Set
2182
2293
  function target(){return currentLocation(api)
2183
2294
  }
2184
2295
  function list(current=target()){return skills()[current.key]??[]
@@ -2216,14 +2327,20 @@ if(activeTarget!==current.key){requests.abortAll()
2216
2327
  promptRequests.abortAll()
2217
2328
  refreshing.clear()
2218
2329
  activeTarget=current.key
2330
+ leases=new Set
2331
+ targets.clear()
2332
+ targets.set(current.key,current)
2219
2333
  }
2220
- return()=>{if(activeTarget!==current.key)
2334
+ const lease=Symbol(current.key)
2335
+ leases.add(lease)
2336
+ return()=>{if(activeTarget!==current.key||!leases.delete(lease)||leases.size>0)
2221
2337
  return
2222
2338
  activeTarget=undefined
2339
+ targets.delete(current.key)
2223
2340
  requests.abortAll()
2224
2341
  promptRequests.abortAll()
2225
2342
  refreshing.clear()
2226
- }},async use(current,name){if(activeTarget&&activeTarget!==current.key)
2343
+ }},async use(current,name){if(activeTarget&&activeTarget!==current.key||target().key!==current.key)
2227
2344
  throw new DOMException("Sidebar context changed","AbortError")
2228
2345
  const request=promptRequests.start(current.key,"insert skill",false,true)
2229
2346
  if(!request)
@@ -2257,11 +2374,6 @@ return rank||left.bucket.localeCompare(right.bucket)||(left.bucket==="Favorites"
2257
2374
 
2258
2375
 
2259
2376
 
2260
-
2261
-
2262
-
2263
-
2264
-
2265
2377
  function SkillConfirmation(props){const icons=useIcons()
2266
2378
  const theme=()=>props.api.theme.current
2267
2379
  return(()=>{var _el$=_$createElement("box"),_el$2=_$createElement("text"),_el$3=_$createTextNode(` Confirmation`),_el$4=_$createElement("box"),_el$5=_$createElement("text"),_el$6=_$createElement("text"),_el$8=_$createElement("text"),_el$9=_$createTextNode(`(`),_el$0=_$createTextNode(`)`),_el$1=_$createElement("box")
@@ -2326,7 +2438,7 @@ return _el$
2326
2438
 
2327
2439
 
2328
2440
  function SkillDetails(props){const icons=useIcons()
2329
- const dimensions=useTerminalDimensions2()
2441
+ const dimensions=useTerminalDimensions3()
2330
2442
  const theme=()=>props.api.theme.current
2331
2443
  return(()=>{var _el$=_$createElement("scrollbox"),_el$2=_$createElement("box"),_el$3=_$createElement("box"),_el$4=_$createElement("text"),_el$5=_$createTextNode(` Description`),_el$6=_$createElement("text"),_el$7=_$createElement("box"),_el$8=_$createElement("text"),_el$9=_$createTextNode(` Source`),_el$0=_$createElement("text")
2332
2444
  _$insertNode(_el$,_el$2)
@@ -2365,11 +2477,67 @@ return _p$
2365
2477
  return _el$
2366
2478
  })()
2367
2479
  }
2368
- function SkillDialog(props){const icons=useIcons()
2369
- const dialogs=useDialogs(props.api)
2370
- const [skipConfirmation,setSkipConfirmation]=createSignal6(false)
2371
- const [active,setActive]=createSignal6("accept")
2480
+
2481
+
2482
+
2483
+
2484
+
2485
+
2486
+
2487
+
2488
+
2489
+
2490
+ function SkillDialogHeader(props){const icons=useIcons()
2372
2491
  const theme=()=>props.api.theme.current
2492
+ return(()=>{var _el$=_$createElement("box"),_el$2=_$createElement("text"),_el$3=_$createTextNode(` `),_el$4=_$createElement("box"),_el$5=_$createElement("text")
2493
+ _$insertNode(_el$,_el$2)
2494
+ _$insertNode(_el$,_el$4)
2495
+ _$setProp(_el$,"flexDirection","row")
2496
+ _$setProp(_el$,"justifyContent","space-between")
2497
+ _$setProp(_el$,"alignItems","center")
2498
+ _$insertNode(_el$2,_el$3)
2499
+ _$setProp(_el$2,"truncate",true)
2500
+ _$setProp(_el$2,"wrapMode","none")
2501
+ _$setProp(_el$2,"flexGrow",1)
2502
+ _$insert(_el$2,()=>icons.icon("skills"),_el$3)
2503
+ _$insert(_el$2,()=>props.name,null)
2504
+ _$insertNode(_el$4,_el$5)
2505
+ _$setProp(_el$4,"flexDirection","row")
2506
+ _$setProp(_el$4,"gap",1)
2507
+ _$setProp(_el$4,"alignItems","center")
2508
+ _$insert(_el$4,_$createComponent(Show2,{get when(){return props.onConfigure
2509
+ },get children(){return _$createComponent(IconControl,{get icon(){return terminalIcon("pin",icons.style())
2510
+ },get foregroundColor(){return _$memo(()=>props.active==="configure")()?theme().selectedListItemText:theme().textMuted
2511
+ },get backgroundColor(){return _$memo(()=>props.active==="configure")()?theme().primary:undefined
2512
+ },onMouseOver:()=>props.onActive("configure"),onMouseUp:()=>props.onConfigure?.()
2513
+ })
2514
+ }}),_el$5)
2515
+ _$insert(_el$4,_$createComponent(BookmarkControl,{get bookmarked(){return props.favorite
2516
+ },get backgroundColor(){return _$memo(()=>props.active==="favorite")()?theme().primary:undefined
2517
+ },get foregroundColor(){return _$memo(()=>!!props.favoriteDisabled)()?theme().textMuted:_$memo(()=>props.active==="favorite")()?theme().selectedListItemText:theme().warning
2518
+ },onMouseOver:()=>{if(!props.favoriteDisabled)
2519
+ props.onActive("favorite")
2520
+ },onMouseUp:()=>{if(!props.favoriteDisabled)
2521
+ props.onFavorite()
2522
+ }}),_el$5)
2523
+ _$setProp(_el$5,"onMouseDown",(event)=>event.stopPropagation())
2524
+ _$setProp(_el$5,"onMouseUp",(event)=>{event.stopPropagation()
2525
+ props.onCancel()
2526
+ })
2527
+ _$insert(_el$5,()=>icons.key("esc"))
2528
+ _$effect((_p$)=>{var _v$=TextAttributes6.BOLD,_v$2=theme().text,_v$3=theme().textMuted
2529
+ _v$!==_p$.e&&(_p$.e=_$setProp(_el$2,"attributes",_v$,_p$.e))
2530
+ _v$2!==_p$.t&&(_p$.t=_$setProp(_el$2,"fg",_v$2,_p$.t))
2531
+ _v$3!==_p$.a&&(_p$.a=_$setProp(_el$5,"fg",_v$3,_p$.a))
2532
+ return _p$
2533
+ },{e:undefined,t:undefined,a:undefined
2534
+ })
2535
+ return _el$
2536
+ })()
2537
+ }
2538
+ function SkillDialog(props){const dialogs=useDialogs(props.api)
2539
+ const [skipConfirmation,setSkipConfirmation]=useDialogState("skill-skip",false)
2540
+ const [active,setActive]=useDialogState("skill-action","accept")
2373
2541
  let body
2374
2542
  function accept(){const isSkip=skipConfirmation()
2375
2543
  dialogs.close()
@@ -2378,6 +2546,8 @@ props.onAccept(isSkip)
2378
2546
  function cancel(){dialogs.back()
2379
2547
  }
2380
2548
  function move(offset){const actions=props.favoriteDisabled?["accept","cancel"]:["accept","cancel","favorite"]
2549
+ if(props.onConfigure)
2550
+ actions.push("configure")
2381
2551
  const index=actions.indexOf(active())
2382
2552
  setActive(actions[(index + offset + actions.length)%actions.length])
2383
2553
  }
@@ -2385,11 +2555,13 @@ function submit(){if(active()==="accept")
2385
2555
  accept()
2386
2556
  else if(active()==="cancel")
2387
2557
  cancel()
2558
+ else if(active()==="configure")
2559
+ props.onConfigure?.(dialogs)
2388
2560
  else if(!props.favoriteDisabled)
2389
2561
  props.onToggleFavorite()
2390
2562
  }
2391
2563
  function confirmationAction(){const action=active()
2392
- return action==="favorite"?undefined:action
2564
+ return action==="favorite"||action==="configure"?undefined:action
2393
2565
  }
2394
2566
  const unregister=props.api.keymap.registerLayer({mode:"modal",priority:1000,commands:[{name:`${PLUGIN_ID}.skill-dialog.scroll-up`,run:()=>body?.scrollBy(-1)
2395
2567
  },{name:`${PLUGIN_ID}.skill-dialog.scroll-down`,run:()=>body?.scrollBy(1)
@@ -2408,41 +2580,15 @@ const unregister=props.api.keymap.registerLayer({mode:"modal",priority:1000,comm
2408
2580
  })
2409
2581
  onCleanup3(unregister)
2410
2582
  return _$createComponent(DialogSurface,{get api(){return props.api
2411
- },get children(){return [(()=>{var _el$=_$createElement("box"),_el$2=_$createElement("text"),_el$3=_$createTextNode(` `),_el$4=_$createElement("box"),_el$5=_$createElement("text")
2412
- _$insertNode(_el$,_el$2)
2413
- _$insertNode(_el$,_el$4)
2414
- _$setProp(_el$,"flexDirection","row")
2415
- _$setProp(_el$,"justifyContent","space-between")
2416
- _$setProp(_el$,"alignItems","center")
2417
- _$insertNode(_el$2,_el$3)
2418
- _$insert(_el$2,()=>icons.icon("skills"),_el$3)
2419
- _$insert(_el$2,()=>props.skill.name,null)
2420
- _$insertNode(_el$4,_el$5)
2421
- _$setProp(_el$4,"flexDirection","row")
2422
- _$setProp(_el$4,"gap",1)
2423
- _$setProp(_el$4,"alignItems","center")
2424
- _$insert(_el$4,_$createComponent(BookmarkControl,{get bookmarked(){return props.favorite
2425
- },get backgroundColor(){return _$memo(()=>active()==="favorite")()?theme().primary:undefined
2426
- },get foregroundColor(){return _$memo(()=>!!props.favoriteDisabled)()?theme().textMuted:_$memo(()=>active()==="favorite")()?theme().selectedListItemText:theme().warning
2427
- },onMouseOver:()=>{if(!props.favoriteDisabled)
2428
- setActive("favorite")
2429
- },onMouseUp:()=>{if(!props.favoriteDisabled)
2430
- props.onToggleFavorite()
2431
- }}),_el$5)
2432
- _$setProp(_el$5,"onMouseDown",(event)=>event.stopPropagation())
2433
- _$setProp(_el$5,"onMouseUp",(event)=>{event.stopPropagation()
2434
- cancel()
2435
- })
2436
- _$insert(_el$5,()=>icons.key("esc"))
2437
- _$effect((_p$)=>{var _v$=TextAttributes6.BOLD,_v$2=theme().text,_v$3=theme().textMuted
2438
- _v$!==_p$.e&&(_p$.e=_$setProp(_el$2,"attributes",_v$,_p$.e))
2439
- _v$2!==_p$.t&&(_p$.t=_$setProp(_el$2,"fg",_v$2,_p$.t))
2440
- _v$3!==_p$.a&&(_p$.a=_$setProp(_el$5,"fg",_v$3,_p$.a))
2441
- return _p$
2442
- },{e:undefined,t:undefined,a:undefined
2443
- })
2444
- return _el$
2445
- })(),_$createComponent(SkillDetails,{get api(){return props.api
2583
+ },get children(){return [_$createComponent(SkillDialogHeader,{get api(){return props.api
2584
+ },get name(){return props.skill.name
2585
+ },get favorite(){return props.favorite
2586
+ },get favoriteDisabled(){return props.favoriteDisabled
2587
+ },get active(){return active()
2588
+ },onActive:setActive,get onFavorite(){return props.onToggleFavorite
2589
+ },get onConfigure(){return props.onConfigure?()=>props.onConfigure?.(dialogs):undefined
2590
+ },onCancel:cancel
2591
+ }),_$createComponent(SkillDetails,{get api(){return props.api
2446
2592
  },get skill(){return props.skill
2447
2593
  },ref:(node)=>body=node
2448
2594
  }),_$createComponent(SkillConfirmation,{get api(){return props.api
@@ -2452,10 +2598,53 @@ return _el$
2452
2598
  })]
2453
2599
  }})
2454
2600
  }
2601
+ function skillUnavailable(controller,skill){const list=controller.list()
2602
+ if(list.every((item)=>!(item.name===skill.name&&item.location===skill.location)))
2603
+ return "Skill is unavailable in this workspace"
2604
+ if(list.filter((item)=>item.name===skill.name).length!==1)
2605
+ return "Multiple sources share this skill name"
2606
+ return
2607
+ }
2608
+ function activateSkill(input){const target=input.controller.target()
2609
+ const route=JSON.stringify(input.api.route.current)
2610
+ const current=()=>target.key===input.controller.target().key&&route===JSON.stringify(input.api.route.current)
2611
+ const report=(error)=>{if(!isAbortError(error))
2612
+ input.api.ui.toast({variant:"error",title:"Skills",message:String(error),duration:5000
2613
+ })
2614
+ }
2615
+ function check(){if(!current())
2616
+ throw new DOMException("Skill target changed; choose it again","AbortError")
2617
+ const reason=skillUnavailable(input.controller,input.skill)
2618
+ if(reason)
2619
+ throw new Error(reason)
2620
+ }
2621
+ async function insert(skip=false){try{check()
2622
+ if(skip)
2623
+ input.access.skipSkillConfirmation(input.skill)
2624
+ input.beforeInsert?.()
2625
+ if(await input.controller.use(target,input.skill.name))
2626
+ await input.access.recordSkillUse?.(input.skill)
2627
+ } catch(error){report(error)
2628
+ }}
2629
+ try{check()
2630
+ } catch(error){report(error)
2631
+ return
2632
+ }
2633
+ if(!input.access.shouldConfirmSkill(input.skill)){insert()
2634
+ return
2635
+ }
2636
+ input.dialogs.open(()=>_$createComponent(SkillDialog,{get api(){return input.api
2637
+ },get skill(){return input.skill
2638
+ },get favorite(){return input.access.isFavoriteSkill?.(input.skill)??false
2639
+ },get favoriteDisabled(){return input.access.ready?.()===false
2640
+ },onToggleFavorite:()=>input.access.toggleFavoriteSkill?.(input.skill),get onConfigure(){return input.onConfigure
2641
+ },onAccept:(skip)=>{insert(skip)
2642
+ }}))
2643
+ }
2455
2644
 
2456
2645
 
2457
2646
  function createSubagentHistory({now=Date.now}={}){const targets=new Map
2458
- const [revision,setRevision]=createSignal7(0)
2647
+ const [revision,setRevision]=createSignal6(0)
2459
2648
  function state(key){let value=targets.get(key)
2460
2649
  if(!value){value={known:new Set,active:new Map,recent:[]}
2461
2650
  targets.set(key,value)
@@ -2512,11 +2701,11 @@ function activeStatus(status){return status?.type==="busy"||status?.type==="retr
2512
2701
  }
2513
2702
  function createSubagentController(api,options={}){const now=options.now??Date.now
2514
2703
  const history=createSubagentHistory({now})
2515
- const [children,setChildren]=createSignal8({})
2516
- const [statuses,setStatuses]=createSignal8({})
2704
+ const [children,setChildren]=createSignal7({})
2705
+ const [statuses,setStatuses]=createSignal7({})
2517
2706
  const refreshing=new Map
2518
2707
  const journals=new Set
2519
- const [unavailable,setUnavailable]=createSignal8({})
2708
+ const [unavailable,setUnavailable]=createSignal7({})
2520
2709
  const targets=new Map
2521
2710
  const remoteFailures=new Map
2522
2711
  const remoteRetryAt=new Map
@@ -2735,7 +2924,7 @@ else if(seconds>=60)
2735
2924
  value=`${Math.floor(seconds / 60)}m ${String(seconds % 60).padStart(2, "0")}s`
2736
2925
  return value
2737
2926
  }
2738
- function createSubagentClock(key){const [now,setNow]=createSignal9(Date.now())
2927
+ function createSubagentClock(key){const [now,setNow]=createSignal8(Date.now())
2739
2928
  createEffect5(()=>{if(key()===undefined)
2740
2929
  return
2741
2930
  setNow(Date.now())
@@ -2745,7 +2934,7 @@ onCleanup4(()=>clearInterval(timer))
2745
2934
  return now
2746
2935
  }
2747
2936
 
2748
- function createTodoController(api){const [sessions,setSessions]=createSignal10({})
2937
+ function createTodoController(api){const [sessions,setSessions]=createSignal9({})
2749
2938
  const refreshing=new Map
2750
2939
  const revisions=new Map
2751
2940
  const requests=createRequestState(api.lifecycle.signal)
@@ -2799,107 +2988,7 @@ activeTarget=undefined
2799
2988
  requests.abortAll()
2800
2989
  refreshing.clear()
2801
2990
  }}}}
2802
- function normalizeTodoState(value){if(!value||typeof value!=="object")
2803
- return{todos:[],guidance:false}
2804
- const state=value
2805
- const statuses=new Set(["pending","in_progress","completed","cancelled"])
2806
- const priorities=new Set(["high","medium","low"])
2807
- const todos=Array.isArray(state.todos)?state.todos.filter((item)=>item&&typeof item.content==="string"&&item.content.trim().length>0&&item.content.length<=512&&statuses.has(item.status)).slice(0,100).map((item)=>({content:item.content.trim(),status:item.status,...priorities.has(item.priority??"")&&{priority:item.priority}})):[]
2808
- return{todos,guidance:state.guidance===true}}
2809
-
2810
- var item={type:"object",properties:{content:{type:"string",minLength:1,maxLength:512},status:{type:"string",enum:["pending","in_progress","completed","cancelled"]},priority:{type:"string",enum:["high","medium","low"]}},required:["content","status"],additionalProperties:false
2811
- }
2812
- var todos={type:"array",items:item,maxItems:100}
2813
- var sessionID={type:"string",minLength:1}
2814
- var output={type:"object",properties:{todos,guidance:{type:"boolean"}},required:["todos","guidance"],additionalProperties:false
2815
- }
2816
- var NavigatorTodoRpc={id:"opencode-navigator.todo",methods:{list:{input:{type:"object",properties:{sessionID},required:["sessionID"],additionalProperties:false},output
2817
- },replace:{input:{type:"object",properties:{sessionID,todos},required:["sessionID","todos"],additionalProperties:false
2818
- },output
2819
- },guidance:{input:{type:"object",properties:{sessionID,enabled:{type:"boolean"}},required:["sessionID","enabled"],additionalProperties:false
2820
- },output
2821
- }},events:{updated:{schema:{type:"object",properties:{sessionID,todos,guidance:{type:"boolean"}},required:["sessionID","todos","guidance"],additionalProperties:false
2822
- }}}};
2823
- function isMissingServer(error){return typeof error==="object"&&error!==null&&"type" in error&&error.type==="rpc.unavailable"
2824
- }
2825
- function createNavigatorTodoController(context,api){const rpc=context.client.rpc(NavigatorTodoRpc)
2826
- const [sessions,setSessions]=createSignal11({})
2827
- const [saving,setSaving]=createSignal11({})
2828
- const [errors,setErrors]=createSignal11({})
2829
- const [missing,setMissing]=createSignal11({})
2830
- const requests=createRequestState(api.lifecycle.signal)
2831
- const refreshing=new Map
2832
- const revisions=new Map
2833
- let activeTarget
2834
- function target(sessionID){const session=api.state.session.get(sessionID)
2835
- const directory=session?.directory??api.state.path.directory
2836
- const workspace=session?.workspaceID
2837
- return{key:JSON.stringify([sessionID,directory,workspace??null]),sessionID,routing:{directory}}}
2838
- function set(key,value){setSessions((current)=>({...current,[key]:normalizeTodoState(value)}))
2839
- }
2840
- function refresh(sessionID,force=false){const current=target(sessionID)
2841
- const pending=refreshing.get(current.key)
2842
- if(pending&&!force)
2843
- return pending
2844
- const revision=revisions.get(current.key)??0
2845
- const requestState=requests.start(current.key,"refresh Navigator todos",current.key in sessions(),force)
2846
- if(!requestState)
2847
- return pending
2848
- const request=rpc.list({sessionID},{location:current.routing,signal:requestState.signal}).then((value)=>{const state=normalizeTodoState(value)
2849
- if(requestState.isCurrent()){setMissing((values)=>({...values,[current.key]:false}))
2850
- if((revisions.get(current.key)??0)===revision)
2851
- set(current.key,state)
2852
- }
2853
- requestState.succeed()
2854
- return state
2855
- }).catch((error)=>{if(requestState.isCurrent()&&!requestState.signal.aborted)
2856
- setMissing((values)=>({...values,[current.key]:isMissingServer(error)}))
2857
- requestState.fail(error)
2858
- throw error
2859
- }).finally(()=>{requestState.finish()
2860
- if(refreshing.get(current.key)===request)
2861
- refreshing.delete(current.key)
2862
- })
2863
- refreshing.set(current.key,request)
2864
- return request
2865
- }
2866
- const unsubscribe=rpc.events.on("updated",(event)=>{const{sessionID}=event.data
2867
- if(typeof sessionID!=="string")
2868
- return
2869
- const current=target(sessionID)
2870
- if(event.location.directory!==current.routing.directory)
2871
- return
2872
- revisions.set(current.key,(revisions.get(current.key)??0) + 1)
2873
- set(current.key,normalizeTodoState(event.data))
2874
- })
2875
- api.lifecycle.onDispose(unsubscribe)
2876
- return{target,list(sessionID){return sessions()[target(sessionID).key]?.todos??[]
2877
- },refresh,state(sessionID){return requests.state(target(sessionID).key)
2878
- },missing(sessionID){return missing()[target(sessionID).key]??false
2879
- },retry(sessionID){return refresh(sessionID,true)
2880
- },guidance(sessionID){const key=target(sessionID).key
2881
- return{enabled:sessions()[key]?.guidance??false,saving:saving()[key]??false,error:errors()[key],available:key in sessions()
2882
- }},async setGuidance(sessionID,enabled){const current=target(sessionID)
2883
- if(!(current.key in sessions())||saving()[current.key])
2884
- return
2885
- setSaving((value)=>({...value,[current.key]:true}))
2886
- setErrors((value)=>({...value,[current.key]:undefined}))
2887
- try{const state=await rpc.guidance({sessionID,enabled},{location:current.routing})
2888
- revisions.set(current.key,(revisions.get(current.key)??0) + 1)
2889
- set(current.key,normalizeTodoState(state))
2890
- } catch(error){setErrors((value)=>({...value,[current.key]:error instanceof Error?error.message:String(error)}))
2891
- } finally{setSaving((value)=>({...value,[current.key]:false}))
2892
- }},activate(sessionID){const key=target(sessionID).key
2893
- if(activeTarget!==key){requests.abortAll()
2894
- refreshing.clear()
2895
- activeTarget=key
2896
- }
2897
- return()=>{if(activeTarget!==key)
2898
- return
2899
- activeTarget=undefined
2900
- requests.abortAll()
2901
- refreshing.clear()
2902
- }}}}
2991
+
2903
2992
  function buildTodoView(todos,mode){const active=[...todos.filter((item)=>item.status==="in_progress"),...todos.filter((item)=>item.status==="pending")]
2904
2993
  const completed=todos.filter((item)=>item.status==="completed")
2905
2994
  const cancelled=todos.filter((item)=>item.status==="cancelled")
@@ -2912,38 +3001,31 @@ return{groups,rows:groups.flatMap((group)=>group.items.map((item)=>({item,group:
2912
3001
 
2913
3002
 
2914
3003
 
2915
-
2916
-
2917
-
2918
-
2919
- function KeyboardHelpDialog(props){const icons=useIcons()
2920
- const theme=()=>props.api.theme.current
2921
- 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+,","Navigator shortcuts: c checks for updates \xB7 u updates Navigator after confirmation",`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`]
2922
- return _$createComponent(DialogSurface,{get api(){return props.api
2923
- },get children(){return [(()=>{var _el$=_$createElement("text"),_el$2=_$createTextNode(` Navigator keyboard help`)
2924
- _$insertNode(_el$,_el$2)
2925
- _$insert(_el$,()=>icons.icon("help"),_el$2)
2926
- _$effect((_p$)=>{var _v$=TextAttributes7.BOLD,_v$2=theme().text
2927
- _v$!==_p$.e&&(_p$.e=_$setProp(_el$,"attributes",_v$,_p$.e))
2928
- _v$2!==_p$.t&&(_p$.t=_$setProp(_el$,"fg",_v$2,_p$.t))
2929
- return _p$
2930
- },{e:undefined,t:undefined
2931
- })
3004
+ var HelpView=lazy2(async ()=>{const path=import.meta.url.includes("/dist/tui.js")?"./sidebar-shortcuts.js":"../../../sidebar-shortcuts"
3005
+ const module=await import(path)
3006
+ return{default:module.KeyboardHelpDialog
3007
+ }})
3008
+ function KeyboardHelpDialog(props){return(()=>{var _el$=_$createElement("box")
3009
+ _$insert(_el$,_$createComponent(Suspense2,{get children(){return _$createComponent(HelpView,props)
3010
+ }}))
2932
3011
  return _el$
2933
- })(),_$createComponent(Index,{get each(){return hints()
2934
- },children:(hint)=>(()=>{var _el$3=_$createElement("text")
2935
- _$setProp(_el$3,"wrapMode","word")
2936
- _$insert(_el$3,hint)
2937
- _$effect((_$p)=>_$setProp(_el$3,"fg",theme().textMuted,_$p))
2938
- return _el$3
2939
3012
  })()
2940
- })]
2941
- }})
2942
3013
  }
2943
- function openKeyboardHelp(api,iconStyle=()=>"nerd",multilineCorners=()=>true){createDialogStack(api,iconStyle,()=>true,multilineCorners).open(()=>_$createComponent(KeyboardHelpDialog,{api
3014
+ function openKeyboardHelp(api,iconStyle=()=>"nerd",multilineCorners=()=>true,shortcuts=[]){createDialogStack(api,iconStyle,()=>true,multilineCorners).open(()=>_$createComponent(KeyboardHelpDialog,{api,shortcuts
2944
3015
  }))
2945
3016
  }
2946
3017
 
3018
+
3019
+
3020
+
3021
+
3022
+
3023
+
3024
+
3025
+
3026
+
3027
+
3028
+
2947
3029
  var QUICK_ACTION_METADATA=[["\uEA73","Rename"],["\uEA82","Timeline"],["\uEBCC","Copy transcript"],["\uEBAC","Export"],["\uEAF5","Compact"],["\uEBEB","Switch session"],["\uEA60","New session"],["\uEB9E","Fork session"],["\uEBCC","Copy last response"],["\uEAA1","First message"],["\uEA9A","Last message"],["\uEA82","Last user message"],["\uEA9A","Next message"],["\uEAA1","Previous message"],["\uEBB3","Auto-approve permissions"]]
2948
3030
  var QUICK_ACTIONS=QUICK_ACTION_IDS.map((command,index)=>({command,icon:QUICK_ACTION_METADATA[index][0],label:QUICK_ACTION_METADATA[index][1]
2949
3031
  }))
@@ -2954,10 +3036,10 @@ return action.label
2954
3036
  const command=api.keymap.getCommands?.({visibility:"registered"}).find((candidate)=>candidate.name===action.command)
2955
3037
  return typeof command?.title==="string"?command.title:action.label
2956
3038
  }
2957
- function createQuickActionRevision(api){const [revision,setRevision]=createSignal12(0)
3039
+ function createQuickActionRevision(api){const [revision,setRevision]=createSignal11(0)
2958
3040
  const unsubscribe=api.keymap.on?.("state",()=>setRevision((value)=>value + 1))
2959
3041
  if(unsubscribe)
2960
- onCleanup5(unsubscribe)
3042
+ onCleanup6(unsubscribe)
2961
3043
  return revision
2962
3044
  }
2963
3045
  function orderQuickActionIds(order,favorites){return [...order.filter((id)=>favorites.has(id)),...order.filter((id)=>!favorites.has(id))]
@@ -2976,6 +3058,29 @@ if(enabled===false||typeof enabled==="function"&&!enabled())
2976
3058
  return "Unavailable in the current session"
2977
3059
  return
2978
3060
  }
3061
+ var sources=new WeakMap
3062
+ function setQuickActionStateSource(api,source){sources.set(api,source)
3063
+ }
3064
+ function currentPermissionMode(api){const title=api.keymap.getCommands?.({visibility:"registered"}).find((command)=>command.name==="permission.mode")?.title
3065
+ if(typeof title!=="string")
3066
+ return
3067
+ if(title.startsWith("Disable auto-approve permissions"))
3068
+ return true
3069
+ return title.startsWith("Enable auto-approve permissions")?false:undefined
3070
+ }
3071
+ function quickActionStates(api,id){if(id==="permission.mode"&&currentPermissionMode(api)!==undefined)
3072
+ return [{id:"on",label:"Auto-approve on"},{id:"off",label:"Auto-approve off"}]
3073
+ if(id==="session.compact"&&sources.has(api))
3074
+ return [{id:"idle",label:"Idle"},{id:"compacting",label:"Compacting"}]
3075
+ return []
3076
+ }
3077
+ function quickActionState(api,id){if(id==="permission.mode"){const mode=currentPermissionMode(api)
3078
+ if(mode===undefined)
3079
+ return
3080
+ return mode?"on":"off"
3081
+ }
3082
+ return sources.get(api)?.(id)
3083
+ }
2979
3084
  var SEARCH_GROUPS=["Skills","Subagents","MCP","Actions"]
2980
3085
  var SEARCH_SECTIONS={Skills:"skills",Subagents:"subagents",MCP:"mcp",Actions:"quick_actions"
2981
3086
  }
@@ -3039,8 +3144,6 @@ return scored.map(({item})=>item)
3039
3144
 
3040
3145
 
3041
3146
 
3042
-
3043
-
3044
3147
  function mixColor(from,to,amount){return RGBA3.fromValues(from.r + (to.r-from.r)*amount,from.g + (to.g-from.g)*amount,from.b + (to.b-from.b)*amount)
3045
3148
  }
3046
3149
  function createSearchDialogController(props){const context=searchContext(props.api)
@@ -3052,7 +3155,7 @@ const [selectedID,setSelectedID]=useDialogState("selection",undefined)
3052
3155
  const [views]=useDialogState("tab-views",new Map)
3053
3156
  const tabViews=views()
3054
3157
  const [scrollTop,setScrollTop]=useDialogState("scroll",0)
3055
- const [refreshing,setRefreshing]=createSignal13(false)
3158
+ const [refreshing,setRefreshing]=createSignal12(false)
3056
3159
  const theme=()=>props.api.theme.current
3057
3160
  const icons=useIcons()
3058
3161
  const commandRevision=createQuickActionRevision(props.api)
@@ -3061,7 +3164,7 @@ const resultColors=createMemo(()=>{const background=parseColor2(theme().backgrou
3061
3164
  const contrast=background.r*0.299 + background.g*0.587 + background.b*0.114>0.5?0:1
3062
3165
  return{title:mixColor(parseColor2(theme().text),RGBA3.fromValues(contrast,contrast,contrast),0.45),description:mixColor(parseColor2(theme().textMuted),background,0.4)
3063
3166
  }})
3064
- const dimensions=useTerminalDimensions3()
3167
+ const dimensions=useTerminalDimensions5()
3065
3168
  let input
3066
3169
  let body
3067
3170
  let pendingScroll=scrollTop()
@@ -3126,11 +3229,6 @@ return
3126
3229
  props.api.ui.toast({title:"Search Everything",variant:"error",message:cause instanceof Error?cause.message:"Action failed",duration:4000
3127
3230
  })
3128
3231
  }
3129
- async function insertSkill(skill){if(!sameContext())
3130
- return
3131
- if(await props.skills.use(skillTarget,skill.name))
3132
- await props.preferences.recordSkillUse(skill)
3133
- }
3134
3232
  function activate(id=active()?.id){if(isDisposed||!sameContext())
3135
3233
  return
3136
3234
  const item=results().find((candidate)=>candidate.id===id)
@@ -3139,26 +3237,15 @@ return
3139
3237
  setSelectedID(item.id)
3140
3238
  if(body)
3141
3239
  setScrollTop(body.scrollTop)
3142
- if(item.group==="Skills"&&props.preferences.shouldConfirmSkill(item.skill)){dialogs.open(()=>_$createComponent(SkillDialog,{get api(){return props.api
3143
- },get skill(){return item.skill
3144
- },get favorite(){return props.preferences.isFavoriteSkill?.(item.skill)??false
3145
- },get favoriteDisabled(){return _$memo(()=>!!props.preferences.ready)()?!props.preferences.ready():false
3146
- },onToggleFavorite:()=>props.preferences.toggleFavoriteSkill?.(item.skill),onAccept:(skip)=>{if(!sameContext())
3147
- return
3148
- if(skip)
3149
- props.preferences.skipSkillConfirmation(item.skill)
3150
- insertSkill(item.skill).catch(report)
3151
- }}))
3240
+ if(item.group==="Skills"){activateSkill({api:props.api,controller:props.skills,access:props.preferences,dialogs,skill:item.skill,beforeInsert:dialogs.close
3241
+ })
3152
3242
  return
3153
3243
  }
3154
3244
  if(item.group==="MCP"){props.mcp.toggle(item.server).catch(report)
3155
3245
  return
3156
3246
  }
3157
3247
  dialogs.close()
3158
- switch(item.group){case "Skills":{insertSkill(item.skill).catch(report)
3159
- break
3160
- }
3161
- case "Subagents":{props.subagents.open(item.sessionID)
3248
+ switch(item.group){case "Subagents":{props.subagents.open(item.sessionID)
3162
3249
  break
3163
3250
  }
3164
3251
  case "Actions":{const target=props.returnTarget?.parent&&!props.returnTarget.isDestroyed?props.returnTarget:null
@@ -3188,9 +3275,10 @@ const unregister=props.api.keymap.registerLayer({mode:"modal",priority:1000,comm
3188
3275
  },{key:"ctrl+r",cmd:`${prefix}.retry`
3189
3276
  }]
3190
3277
  })
3191
- onCleanup6(()=>{isDisposed=true
3278
+ onCleanup7(()=>{isDisposed=true
3192
3279
  unregister()
3193
3280
  })
3281
+ onCleanup7(props.skills.activate?.(skillTarget)??(()=>{}))
3194
3282
  onMount(()=>{input?.focus()
3195
3283
  refresh().catch(report)
3196
3284
  })
@@ -3367,7 +3455,7 @@ _$effect((_$p)=>_$setProp(_el$2,"fg",model.theme().error,_$p))
3367
3455
  return _el$2
3368
3456
  })()
3369
3457
  }),null)
3370
- _$insert(_el$,_$createComponent(Show2,{get when(){return model.results().length
3458
+ _$insert(_el$,_$createComponent(Show3,{get when(){return model.results().length
3371
3459
  },get fallback(){return(()=>{var _el$8=_$createElement("text"),_el$9=_$createTextNode(` `)
3372
3460
  _$insertNode(_el$8,_el$9)
3373
3461
  _$insert(_el$8,()=>model.icons.icon(model.loading()?"pending":"search"),_el$9)
@@ -3375,7 +3463,7 @@ _$insert(_el$8,()=>model.loading()?"Loading sources\u2026":"No matching results"
3375
3463
  _$effect((_$p)=>_$setProp(_el$8,"fg",model.theme().textMuted,_$p))
3376
3464
  return _el$8
3377
3465
  })()
3378
- },get children(){return _$createComponent(Show2,{keyed:true,get when(){return model.queryScope()
3466
+ },get children(){return _$createComponent(Show3,{keyed:true,get when(){return model.queryScope()
3379
3467
  },children:(_scope)=>_$createComponent(For3,{get each(){return model.results().map((item)=>item.id)
3380
3468
  },children:(id)=>_$createComponent(SearchResultRow,{model,id
3381
3469
  })
@@ -3435,9 +3523,9 @@ createEffect7(()=>{const key=props.preferences.searchKey()
3435
3523
  const remove=props.api.keymap.registerLayer({mode:"base",bindings:[{key,cmd:SEARCH_COMMAND
3436
3524
  }]
3437
3525
  })
3438
- onCleanup7(remove)
3526
+ onCleanup8(remove)
3439
3527
  })
3440
- onCleanup7(()=>{isDisposed=true
3528
+ onCleanup8(()=>{isDisposed=true
3441
3529
  unregister()
3442
3530
  for(const timer of timers)
3443
3531
  clearTimeout(timer)
@@ -3668,8 +3756,8 @@ return _el$
3668
3756
  }
3669
3757
  function FirstRunWizard(props){const icons=useIcons()
3670
3758
  const dialogs=useDialogs(props.api)
3671
- const [active,setActive]=createSignal14(0)
3672
- const [step,setStep]=createSignal14(0)
3759
+ const [active,setActive]=createSignal13(0)
3760
+ const [step,setStep]=createSignal13(0)
3673
3761
  const theme=()=>props.api.theme.current
3674
3762
  const sections=SECTION_DEFINITIONS.filter((section)=>supportsSidebarSection(props.api,section.name))
3675
3763
  const finishIndex=sections.length
@@ -3710,7 +3798,7 @@ const unregister=props.api.keymap.registerLayer({mode:"modal",priority:1000,comm
3710
3798
  },{key:"return",cmd:`${PLUGIN_ID}.wizard.select`
3711
3799
  }]
3712
3800
  })
3713
- onCleanup8(unregister)
3801
+ onCleanup9(unregister)
3714
3802
  return _$createComponent(DialogSurface,{get api(){return props.api
3715
3803
  },get children(){return [(()=>{var _el$=_$createElement("box"),_el$2=_$createElement("text"),_el$3=_$createTextNode(` Navigator setup`),_el$4=_$createElement("text"),_el$5=_$createTextNode(`Step `),_el$6=_$createTextNode(`/`),_el$7=_$createTextNode(` \xB7 `)
3716
3804
  _$insertNode(_el$,_el$2)
@@ -3737,7 +3825,7 @@ return _p$
3737
3825
  },{e:undefined,t:undefined,a:undefined
3738
3826
  })
3739
3827
  return _el$
3740
- })(),_$createComponent(Show3,{get when(){return configuring()
3828
+ })(),_$createComponent(Show4,{get when(){return configuring()
3741
3829
  },get fallback(){return _$createComponent(OnboardingStep,{get api(){return props.api
3742
3830
  },get preferences(){return props.preferences
3743
3831
  },get step(){return ONBOARDING_STEPS[step()]
@@ -3794,7 +3882,7 @@ _$insertNode(_el$,_el$6)
3794
3882
  _$setProp(_el$,"flexDirection","row")
3795
3883
  _$setProp(_el$,"justifyContent","space-between")
3796
3884
  _$setProp(_el$2,"flexGrow",1)
3797
- _$insert(_el$2,_$createComponent(Show4,{get when(){return props.onRefresh
3885
+ _$insert(_el$2,_$createComponent(Show5,{get when(){return props.onRefresh
3798
3886
  },get children(){var _el$3=_$createElement("text"),_el$4=_$createTextNode(` Refresh (`),_el$5=_$createTextNode(`)`)
3799
3887
  _$insertNode(_el$3,_el$4)
3800
3888
  _$insertNode(_el$3,_el$5)
@@ -3855,9 +3943,9 @@ return _el$
3855
3943
  function PresetPreviewFrame(props){const icons=useIcons()
3856
3944
  const dialogs=useDialogs(props.api)
3857
3945
  const theme=()=>props.api.theme.current
3858
- const dimensions=useTerminalDimensions4()
3946
+ const dimensions=useTerminalDimensions6()
3859
3947
  const scroll=useDialogScroll()
3860
- const [active,setActive]=createSignal15("apply")
3948
+ const [active,setActive]=createSignal14("apply")
3861
3949
  let body
3862
3950
  const prefix=`${PLUGIN_ID}.preset-preview`
3863
3951
  function activate(action){if(!props.valid()){dialogs.close()
@@ -3886,7 +3974,7 @@ const unregister=props.api.keymap.registerLayer({mode:"modal",priority:1000,comm
3886
3974
  },{key:"ctrl+r",cmd:`${prefix}.refresh`
3887
3975
  }]
3888
3976
  })
3889
- onCleanup9(unregister)
3977
+ onCleanup10(unregister)
3890
3978
  createEffect8(()=>{if(!props.valid())
3891
3979
  dialogs.close()
3892
3980
  })
@@ -3934,7 +4022,7 @@ return _p$
3934
4022
  },{e:undefined,t:undefined,a:undefined
3935
4023
  })
3936
4024
  return _el$5
3937
- })(),_$createComponent(Show5,{get when(){return props.blocked||props.notice
4025
+ })(),_$createComponent(Show6,{get when(){return props.blocked||props.notice
3938
4026
  },get children(){var _el$7=_$createElement("box"),_el$8=_$createElement("text"),_el$9=_$createElement("text")
3939
4027
  _$insertNode(_el$7,_el$8)
3940
4028
  _$insertNode(_el$7,_el$9)
@@ -4146,548 +4234,54 @@ dialogs.open(()=>_$createComponent(SelectionMenu,{api,title:"MCP presets",get op
4146
4234
 
4147
4235
 
4148
4236
 
4237
+ var Content=lazy3(async ()=>{const path=import.meta.url.includes("/dist/")?"./sidebar-settings.js":"./settings-dialog-content"
4238
+ const module=await import(path)
4239
+ return{default:module.SettingsDialog
4240
+ }})
4241
+ function SettingsDialog(props){return(()=>{var _el$=_$createElement("box")
4242
+ _$insert(_el$,_$createComponent(Suspense3,{get children(){return _$createComponent(Content,props)
4243
+ }}))
4244
+ return _el$
4245
+ })()
4246
+ }
4247
+ function openSettings(api,preferences,activeValue,mcp,skills){createDialogStack(api,preferences.lspIconStyle,()=>true,preferences.cornerFont).open(()=>_$createComponent(SettingsDialog,{api,preferences,mcp,skills,activeValue
4248
+ }),"xlarge")
4249
+ }
4149
4250
 
4150
4251
 
4151
-
4152
-
4153
-
4154
-
4155
-
4156
-
4157
-
4158
-
4159
- function behaviorSettingsOptions(api,preferences,icons){const permission=preferences.autoApprovePermissions()
4160
- const permissionDescription=permission?"on for new sessions":"off for new sessions"
4161
- return [...supportsPermissionMode(api)?[{title:`${icons.icon(permission === true ? "checked" : "unchecked")} Default auto-approve permissions`,value:"auto_approve_permissions",description:permission===undefined?"follow OpenCode startup mode":permissionDescription
4162
- }]:[],{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"
4163
- },{title:`${icons.icon(preferences.selectedPersistMcp() ? "checked" : "unchecked")} Remember MCP states`,value:"persist_mcp",description:preferences.selectedPersistMcp()?"on":"off"
4164
- },{title:`${icons.icon("settings")} Icon style`,value:"lsp_icon_style",description:preferences.selectedLspIconStyle()==="nerd"?"Nerd Font":"Text fallback"
4165
- },{title:`${icons.icon(preferences.selectedCornerFont() ? "checked" : "unchecked")} Multiline corner font`,value:"corner_font",description:preferences.selectedCornerFont()?"Installed":"Not installed \xB7 rectangular highlights"
4166
- },{title:`${icons.icon("sections")} Row density`,value:"row_density",description:preferences.selectedRowDensity()==="compact"?"Compact":"Comfortable"
4167
- },{title:`${icons.icon("sections")} Sidebar shortcut`,value:"toggle_key",description:preferences.selectedToggleKey()
4168
- },{title:`${icons.icon("selected")} Focus shortcut`,value:"focus_key",description:preferences.selectedFocusKey()
4169
- },{title:`${icons.icon("search")} Search Everything shortcut`,value:"search_key",description:preferences.selectedSearchKey?.()??DEFAULT_SEARCH_KEY
4170
- },{title:`${icons.icon("retry")} Limits refresh interval`,value:"limits_refresh",description:`${preferences.selectedLimitsRefreshMinutes()} min \xB7 minimum 1 min`
4171
- }]
4252
+ async function load(input){const path=import.meta.url.includes("/dist/")?"./toolbar-settings.js":"./open-toolbar"
4253
+ try{return await import(path)
4254
+ } catch(error){input.api.ui.toast({variant:"error",title:"Toolbar",message:String(error)})
4255
+ return
4256
+ }}
4257
+ async function openToolbarManager(input){const route=JSON.stringify(input.api.route.current)
4258
+ const target=input.skills?.target().key
4259
+ const wasOpen=input.api.ui.dialog.open
4260
+ const module=await load(input)
4261
+ if(route===JSON.stringify(input.api.route.current)&&target===input.skills?.target().key&&(!wasOpen||input.api.ui.dialog.open)&&!input.api.lifecycle?.signal?.aborted)
4262
+ module?.openToolbarManager(input)
4263
+ }
4264
+ async function openToolbarPin(input){const route=JSON.stringify(input.api.route.current)
4265
+ const target=input.skills?.target().key
4266
+ const wasOpen=input.api.ui.dialog.open
4267
+ const module=await load(input)
4268
+ if(route===JSON.stringify(input.api.route.current)&&target===input.skills?.target().key&&(!wasOpen||input.api.ui.dialog.open)&&!input.api.lifecycle?.signal?.aborted)
4269
+ module?.openToolbarPin(input)
4172
4270
  }
4173
- function titleVisibilityOptions(api,preferences,icons){if(!supportsTitleVisibility(api))
4174
- return []
4175
- const title=preferences.selectedShowSessionTitle()
4176
- const date=preferences.selectedShowSessionDate()
4177
- return [{title:`${icons.icon(title ? "checked" : "unchecked")} Session title`,value:"session_title",description:title?"visible":"hidden"
4178
- },{title:`${icons.icon(date ? "checked" : "unchecked")} Creation date`,value:"session_date",description:date?"visible":"hidden"
4271
+ 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)
4272
+ },{name:`${PLUGIN_ID}.toolbar`,title:"Manage pinned toolbar",category:"Navigator",namespace:"palette",enabled:()=>["home","session"].includes(props.api.route.current.name),run:()=>{openToolbarManager(props)
4273
+ }}],bindings:[{key:{name:",",ctrl:true
4274
+ },cmd:`${PLUGIN_ID}.settings`
4179
4275
  }]
4180
- }
4181
- function createSettingsGroups(api,preferences,icons){const supportedSections=()=>SIDEBAR_SECTIONS.filter((name)=>supportsSidebarSection(api,name))
4182
- 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"
4183
- },{title:`${icons.icon(preferences.preferenceScope() === "worktree" ? "radioOn" : "radioOff")} Current worktree`,value:"scope:worktree",description:preferences.canUseWorktreeScope()?preferences.preferenceScopeLabel():"unavailable outside a worktree"
4184
- }]
4185
- },{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"
4186
- })),{title:`${icons.icon("add")} Save as\u2026`,value:"save_preset",description:"create a preset from the current layout"
4187
- }]
4188
- },{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)
4189
- 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"
4190
- }})]
4191
- },{id:"behavior",tab:"Behavior",title:"Behavior",options:behaviorSettingsOptions(api,preferences,icons)
4192
- },{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`
4193
- },{title:`${icons.icon("export")} Copy portable settings`,value:"export_settings",description:"versioned layout and MCP JSON"
4194
- },{title:`${icons.icon("add")} Import portable settings\u2026`,value:"import_settings",description:"preview pasted JSON before applying"
4195
- },{title:`${icons.icon("retry")} Reload settings from file`,value:"reload_settings",description:"sync saved changes from other OpenCode sessions"
4196
- },{title:`${icons.icon("reset")} Restore configured layout`,value:"reset_sections",description:"visibility and expansion"
4197
- },{title:`${icons.icon("reset")} Restore configured behavior`,value:"reset_settings",description:"startup, MCP memory, icons, shortcuts, limits, actions"
4198
- },{title:`${icons.icon("reset")} Clear remembered MCP states`,value:"reset_mcp",description:`scope: ${preferences.preferenceScopeLabel()}`
4199
- },{title:`${icons.section("skills")} Manage trusted skills`,value:"trusted_skills",description:`${preferences.skippedSkillCount()} trusted`
4200
- },{title:`${icons.icon("help")} Open quick setup guide`,value:"wizard",description:"tips and section settings"
4201
- }]
4202
- }])
4203
- const orderedGroups=createMemo7(()=>["sections","scope","presets","behavior","defaults"].map((id)=>groups().find((group)=>group.id===id)))
4204
- return orderedGroups
4205
- }
4206
- 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")
4207
- return
4208
- if(input.options()[input.active()]?.value==="mcp")
4209
- input.openMcpGroups()
4210
- if(input.options()[input.active()]?.value==="skills")
4211
- input.openSkillGroups()
4212
- }},{name:`${PLUGIN_ID}.settings.quick-actions`,run:()=>{if(input.activeGroup()==="sections"&&input.options()[input.active()]?.value==="quick_actions")
4213
- input.openQuickActions()
4214
- }},{name:`${PLUGIN_ID}.settings.item-limit`,run:()=>{const section=input.options()[input.active()]?.value
4215
- if(input.activeGroup()==="sections"&&SIDEBAR_SECTIONS.includes(section))
4216
- input.openLimitPrompt(section)
4217
- }},{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`}]
4218
- })
4219
- }
4220
-
4221
-
4222
-
4223
-
4224
-
4225
-
4226
-
4227
-
4228
-
4229
-
4230
-
4231
- function openLimitsRefreshPrompt(api,preferences,dialogs){const scope=preferences.preferenceScopeLabel()
4232
- dialogs.prompt({title:"Limits refresh interval",description:()=>(()=>{var _el$=_$createElement("text")
4233
- _$insertNode(_el$,_$createTextNode(`Automatic refresh in minutes (minimum 1; default 5). Manual Refresh stays immediate.`))
4234
- _$effect((_$p)=>_$setProp(_el$,"fg",api.theme.current.textMuted,_$p))
4235
- return _el$
4236
- })(),value:String(preferences.selectedLimitsRefreshMinutes()),onConfirm(value){if(preferences.preferenceScopeLabel()!==scope)
4237
- throw new Error("Preference scope changed; reopen this setting")
4238
- if(!/^\d+$/.test(value.trim()))
4239
- throw new Error("Enter whole minutes (at least 1 minute)")
4240
- preferences.setLimitsRefreshMinutes(Number(value))
4241
- dialogs.back()
4242
- }})
4243
- }
4244
- function createSettingsSelection(input){const dialogClosed=()=>("open" in input.api.ui.dialog)&&!input.api.ui.dialog.open
4245
- function openLimitPrompt(section){const index=input.options().findIndex((option)=>option.value===section)
4246
- if(index!==-1)
4247
- input.setActive(index)
4248
- input.dialogs.prompt({title:`${SECTION_DEFINITIONS.find((item) => item.name === section).label} item limit`,description:()=>(()=>{var _el$=_$createElement("text")
4249
- _$insertNode(_el$,_$createTextNode(`Visible items before Show all. Enter 0 for All.`))
4250
- _$effect((_$p)=>_$setProp(_el$,"fg",input.api.theme.current.textMuted,_$p))
4251
- return _el$
4252
- })(),value:String(input.preferences.selectedSectionItemLimit(section)),onConfirm(value){if(!/^\d+$/.test(value.trim()))
4253
- throw new Error("Enter a non-negative whole number (0 for All)")
4254
- input.preferences.setSectionItemLimit(section,Number(value))
4255
- input.dialogs.back()
4256
- }})
4257
- }
4258
- function openShortcut(value){const bindings={toggle_key:{title:"Sidebar shortcut",get:input.preferences.selectedToggleKey,set:input.preferences.setToggleKey
4259
- },focus_key:{title:"Focus shortcut",get:input.preferences.selectedFocusKey,set:input.preferences.setFocusKey
4260
- },search_key:{title:"Search Everything shortcut",get:input.preferences.selectedSearchKey,set:input.preferences.setSearchKey
4261
- }}
4262
- const binding=bindings[value]
4263
- input.dialogs.prompt({title:binding.title,description:()=>(()=>{var _el$3=_$createElement("text")
4264
- _$insertNode(_el$3,_$createTextNode(`Use OpenCode key syntax, for example alt+s.`))
4265
- _$effect((_$p)=>_$setProp(_el$3,"fg",input.api.theme.current.textMuted,_$p))
4266
- return _el$3
4267
- })(),value:binding.get(),onConfirm(key){binding.set(key)
4268
- input.dialogs.back()
4269
- }})
4270
- }
4271
- function saveLayout(){input.preferences.saveLayoutAsDefault().then(()=>input.api.ui.toast({variant:"success",title:"Navigator settings",message:"Current layout saved as default",duration:3000
4272
- })).catch((error)=>input.api.ui.toast({variant:"error",title:"Navigator settings",message:error instanceof Error?error.message:"Failed to save the default layout",duration:5000
4273
- }))
4274
- }
4275
- function exportSettings(){const copied=input.api.renderer.copyToClipboardOSC52(input.preferences.exportPortableSettings())
4276
- input.api.ui.toast({variant:copied?"success":"warning",title:"Portable settings",message:copied?"Layout and MCP settings copied as JSON":"Terminal clipboard is unavailable",duration:4000
4277
- })
4278
- }
4279
- function importSettings(){const path=import.meta.url.includes("/dist/tui.js")?"./settings-import.js":"../ui/settings-import-dialog"
4280
- import(path).then((module)=>{if(!dialogClosed())
4281
- module.openSettingsImport(input)
4282
- }).catch((error)=>input.api.ui.toast({variant:"error",title:"Portable settings",message:String(error)
4283
- }))
4284
- }
4285
- function select(value=input.options()[input.active()]?.value){if(!value)
4286
- return
4287
- const index=input.options().findIndex((option)=>option.value===value)
4288
- if(index!==-1)
4289
- input.setActive(index)
4290
- if(value==="scope:global"||value==="scope:worktree")
4291
- input.preferences.setPreferenceScope(value==="scope:global"?"global":"worktree")
4292
- else if(value.startsWith("preset:custom:"))
4293
- input.openPreset(decodeURIComponent(value.slice("preset:custom:".length)))
4294
- else
4295
- switch(value){case "save_preset":{input.promptPreset()
4296
- break
4297
- }
4298
- case "save_layout":{saveLayout()
4299
- break
4300
- }
4301
- case "export_settings":{exportSettings()
4302
- break
4303
- }
4304
- case "import_settings":{importSettings()
4305
- break
4306
- }
4307
- case "reload_settings":{input.preferences.reloadFromFile().then(()=>input.api.ui.toast({variant:"success",title:"Navigator settings",message:"Saved settings reloaded",duration:3000
4308
- })).catch((error)=>input.api.ui.toast({variant:"error",title:"Navigator settings",message:error instanceof Error?error.message:"Could not reload saved settings",duration:5000
4309
- }))
4310
- break
4311
- }
4312
- case "reset_sections":{input.preferences.resetSections()
4313
- break
4314
- }
4315
- case "session_title":{input.preferences.toggleSessionTitleVisibility()
4316
- break
4317
- }
4318
- case "session_date":{input.preferences.toggleSessionDateVisibility()
4319
- break
4320
- }
4321
- case "persist_mcp":{input.preferences.toggleMcpPersistence()
4322
- break
4323
- }
4324
- case "limits_refresh":{openLimitsRefreshPrompt(input.api,input.preferences,input.dialogs)
4325
- break
4326
- }
4327
- case "start_in_chat":{input.preferences.toggleStartInChat()
4328
- break
4329
- }
4330
- case "auto_approve_permissions":{input.preferences.setAutoApprovePermissions(input.preferences.autoApprovePermissions()!==true)
4331
- break
4332
- }
4333
- case "lsp_icon_style":{input.preferences.toggleLspIconStyle()
4334
- break
4335
- }
4336
- case "corner_font":{input.preferences.toggleCornerFont()
4337
- break
4338
- }
4339
- case "row_density":{input.preferences.toggleRowDensity()
4340
- break
4341
- }
4342
- case "toggle_key":{openShortcut("toggle_key")
4343
- break
4344
- }
4345
- case "focus_key":{openShortcut("focus_key")
4346
- break
4347
- }
4348
- case "search_key":{openShortcut("search_key")
4349
- break
4350
- }
4351
- case "reset_settings":{input.preferences.resetPluginSettings()
4352
- break
4353
- }
4354
- case "reset_mcp":{input.preferences.resetMcpStates()
4355
- break
4356
- }
4357
- case "trusted_skills":{const path=import.meta.url.includes("/dist/tui.js")?"./trusted-skills.js":"../ui/trusted-skills-dialog"
4358
- import(path).then((module)=>{if(dialogClosed())
4359
- return
4360
- const{TrustedSkillsDialog
4361
- }=module
4362
- input.dialogs.open(()=>_$createComponent(TrustedSkillsDialog,{get api(){return input.api
4363
- },get preferences(){return input.preferences
4364
- }}))
4365
- }).catch((error)=>input.api.ui.toast({variant:"error",title:"Trusted skills",message:String(error)
4366
- }))
4367
- break
4368
- }
4369
- case "wizard":{input.dialogs.open(()=>_$createComponent(FirstRunWizard,{get api(){return input.api
4370
- },get preferences(){return input.preferences
4371
- }}))
4372
- break
4373
- }
4374
- default:{input.preferences.toggleSelectedSection(value)
4375
- }}}
4376
- function openQuickActions(){input.setActive(input.options().findIndex((option)=>option.value==="quick_actions"))
4377
- const path=import.meta.url.includes("/dist/tui.js")?"./quick-actions-settings.js":"../ui/quick-actions-dialog"
4378
- import(path).then((module)=>{if(dialogClosed())
4379
- return
4380
- const{QuickActionsDialog
4381
- }=module
4382
- input.dialogs.open(()=>_$createComponent(QuickActionsDialog,{get api(){return input.api
4383
- },get preferences(){return input.preferences
4384
- }}))
4385
- }).catch((error)=>{input.api.ui.toast({variant:"error",title:"Quick actions",message:String(error),duration:4000
4386
- })
4387
- })
4388
- }
4389
- function openMcpGroups(){if(!input.mcp)
4390
- return
4391
- input.setActive(input.options().findIndex((option)=>option.value==="mcp"))
4392
- const path=import.meta.url.includes("/dist/tui.js")?"./mcp-groups.js":"../ui/mcp-groups-dialog"
4393
- import(path).then((module)=>{if(dialogClosed())
4394
- return
4395
- const{McpGroupsDialog
4396
- }=module
4397
- input.dialogs.open(()=>_$createComponent(McpGroupsDialog,{get api(){return input.api
4398
- },get preferences(){return input.preferences
4399
- },get mcp(){return input.mcp
4400
- }}))
4401
- }).catch((error)=>{input.api.ui.toast({variant:"error",title:"MCP groups",message:String(error),duration:4000
4402
- })
4403
- })
4404
- }
4405
- function openSkillGroups(){if(!input.skills)
4406
- return
4407
- input.setActive(input.options().findIndex((option)=>option.value==="skills"))
4408
- const path=import.meta.url.includes("/dist/tui.js")?"./skill-groups.js":"../ui/skill-groups-dialog"
4409
- import(path).then((module)=>{if(dialogClosed())
4410
- return
4411
- const{SkillGroupsDialog
4412
- }=module
4413
- input.dialogs.open(()=>_$createComponent(SkillGroupsDialog,{get api(){return input.api
4414
- },get preferences(){return input.preferences
4415
- },get skills(){return input.skills
4416
- }}))
4417
- }).catch((error)=>{input.api.ui.toast({variant:"error",title:"Skill groups",message:String(error),duration:4000
4418
- })
4419
- })
4420
- }
4421
- return{openLimitPrompt,openMcpGroups,openSkillGroups,openQuickActions,select
4422
- }}
4423
- function createSettingsDialogController(props){let body
4424
- const theme=()=>props.api.theme.current
4425
- const icons=useIcons()
4426
- const dialogs=useDialogs(props.api)
4427
- const scroll=useDialogScroll()
4428
- const dimensions=useTerminalDimensions6()
4429
- const bodyHeight=createMemo8(()=>Math.max(4,Math.floor(dimensions().height*0.75)-10))
4430
- const orderedGroups=createSettingsGroups(props.api,props.preferences,icons)
4431
- const initialGroup=orderedGroups().find((group)=>group.options.some((option)=>option.value===props.activeValue))
4432
- const [activeGroup,setActiveGroup]=useDialogState("tab",initialGroup?.id??orderedGroups()[0].id)
4433
- const options=createMemo8(()=>orderedGroups().find((group)=>group.id===activeGroup())?.options??[])
4434
- const optionId=(value)=>`${PLUGIN_ID}.settings.${value}`
4435
- const initialActive=options().findIndex((option)=>option.value===props.activeValue)
4436
- const [active,setActive]=useDialogState("selection",Math.max(0,initialActive))
4437
- createEffect11(()=>{if(active()>=options().length)
4438
- setActive(Math.max(0,options().length-1))
4439
- })
4440
- const contentHeight=createMemo8(()=>Math.min(bodyHeight(),Math.max(1,options().length*2-1)))
4441
- const footerHint=createMemo8(()=>{const common=`${icons.key("tab")} switch \xB7 ${icons.key("up/down")} navigate`
4442
- if(activeGroup()==="sections")
4443
- 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`
4444
- if(activeGroup()==="presets")
4445
- return `${common} \xB7 ${icons.key("enter")} manage`
4446
- if(activeGroup()==="behavior")
4447
- return `${common} \xB7 ${icons.key("enter")} change`
4448
- if(activeGroup()==="defaults")
4449
- return `${common} \xB7 ${icons.key("enter")} run`
4450
- return `${common} \xB7 ${icons.key("enter")} select`
4451
- })
4452
- onMount4(()=>{queueMicrotask(()=>{const option=options()[active()]
4453
- if(option)
4454
- body?.scrollChildIntoView(optionId(option.value))
4455
- })
4456
- })
4457
- function move(offset){const next=(active() + offset + options().length)%options().length
4458
- setActive(next)
4459
- const option=options()[next]
4460
- if(option)
4461
- body?.scrollChildIntoView(optionId(option.value))
4462
- }
4463
- function switchGroup(offset){const index=orderedGroups().findIndex((group)=>group.id===activeGroup())
4464
- const group=orderedGroups()[(index + offset + orderedGroups().length)%orderedGroups().length]
4465
- setActiveGroup(group.id)
4466
- setActive(0)
4467
- queueMicrotask(()=>{const option=options()[0]
4468
- if(option)
4469
- body?.scrollChildIntoView(optionId(option.value))
4470
- })
4471
- }
4472
- function reorder(value,direction){if(!value||!SIDEBAR_SECTIONS.includes(value))
4473
- return
4474
- props.preferences.moveSelectedSection(value,direction)
4475
- queueMicrotask(()=>{const next=options().findIndex((candidate)=>candidate.value===value)
4476
- if(next===-1)
4477
- return
4478
- setActive(next)
4479
- body?.scrollChildIntoView(optionId(value))
4480
- })
4481
- }
4482
- function runPresetAction(action,name){const path=import.meta.url.includes("/dist/tui.js")?"./layout-preset-actions.js":"./layout-preset-actions"
4483
- import(path).then((module)=>{if("open" in props.api.ui.dialog&&!props.api.ui.dialog.open)
4484
- return
4485
- const factory=module.createLayoutPresetActions
4486
- const actions=factory({api:props.api,preferences:props.preferences,mcp:props.mcp,dialogs
4487
- })
4488
- if(action==="open"&&name)
4489
- actions.open(name)
4490
- else
4491
- actions.prompt()
4492
- }).catch((error)=>props.api.ui.toast({variant:"error",title:"Layout presets",message:String(error)
4493
- }))
4494
- }
4495
- const selection=createSettingsSelection({api:props.api,preferences:props.preferences,mcp:props.mcp,skills:props.skills,dialogs,options,active,setActive,openPreset:(name)=>runPresetAction("open",name),promptPreset:()=>runPresetAction("prompt")
4496
- })
4497
- 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
4498
- })
4499
- onCleanup11(unregister)
4500
- 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
4501
- scroll.ref(node)
4502
- },restoreScroll:scroll.restore,saveScroll:scroll.save,theme
4503
- }}
4504
-
4505
-
4506
-
4507
-
4508
-
4509
-
4510
-
4511
-
4512
-
4513
-
4514
- function SettingsOptionRow(props){const model=props.controller
4515
- const index=()=>model.options().findIndex((candidate)=>candidate.value===props.option.value)
4516
- const selected=()=>model.active()===index()
4517
- const section=()=>props.option.value
4518
- return _$createComponent(SelectionBox,{get id(){return model.optionId(props.option.value)
4519
- },flexDirection:"row",gap:2,paddingLeft:1,paddingRight:1,get backgroundColor(){return _$memo(()=>!!selected())()?model.theme().backgroundElement:undefined
4520
- },onMouseOver:()=>model.setActive(index()),onMouseDown:(event)=>event.stopPropagation(),onMouseUp:(event)=>{event.stopPropagation()
4521
- model.select(props.option.value)
4522
- },get children(){return [(()=>{var _el$=_$createElement("text")
4523
- _$setProp(_el$,"flexShrink",0)
4524
- _$insert(_el$,()=>props.option.title)
4525
- _$effect((_p$)=>{var _v$=selected()?TextAttributes15.BOLD:undefined,_v$2=model.theme().text
4526
- _v$!==_p$.e&&(_p$.e=_$setProp(_el$,"attributes",_v$,_p$.e))
4527
- _v$2!==_p$.t&&(_p$.t=_$setProp(_el$,"fg",_v$2,_p$.t))
4528
- return _p$
4529
- },{e:undefined,t:undefined
4530
- })
4531
- return _el$
4532
- })(),(()=>{var _el$2=_$createElement("text")
4533
- _$setProp(_el$2,"flexGrow",1)
4534
- _$insert(_el$2,()=>props.option.description)
4535
- _$effect((_$p)=>_$setProp(_el$2,"fg",model.theme().borderSubtle,_$p))
4536
- return _el$2
4537
- })(),_$createComponent(Show6,{get when(){return SIDEBAR_SECTIONS.includes(section())
4538
- },get children(){var _el$3=_$createElement("box"),_el$8=_$createElement("text"),_el$9=_$createTextNode(` Items: `),_el$0=_$createElement("text"),_el$1=_$createElement("text")
4539
- _$insertNode(_el$3,_el$8)
4540
- _$insertNode(_el$3,_el$0)
4541
- _$insertNode(_el$3,_el$1)
4542
- _$setProp(_el$3,"flexDirection","row")
4543
- _$setProp(_el$3,"flexShrink",0)
4544
- _$setProp(_el$3,"gap",1)
4545
- _$insert(_el$3,_$createComponent(Show6,{get when(){return props.option.value==="quick_actions"
4546
- },get children(){var _el$4=_$createElement("text"),_el$5=_$createTextNode(` Actions`)
4547
- _$insertNode(_el$4,_el$5)
4548
- _$setProp(_el$4,"onMouseDown",(event)=>event.stopPropagation())
4549
- _$setProp(_el$4,"onMouseUp",(event)=>{event.stopPropagation()
4550
- model.openQuickActions()
4551
- })
4552
- _$insert(_el$4,()=>model.icons.icon("actions"),_el$5)
4553
- _$effect((_$p)=>_$setProp(_el$4,"fg",model.theme().accent,_$p))
4554
- return _el$4
4555
- }}),_el$8)
4556
- _$insert(_el$3,_$createComponent(Show6,{get when(){return props.option.value==="mcp"||props.option.value==="skills"
4557
- },get children(){var _el$6=_$createElement("text"),_el$7=_$createTextNode(` Groups`)
4558
- _$insertNode(_el$6,_el$7)
4559
- _$setProp(_el$6,"onMouseDown",(event)=>event.stopPropagation())
4560
- _$setProp(_el$6,"onMouseUp",(event)=>{event.stopPropagation()
4561
- if(props.option.value==="skills")
4562
- model.openSkillGroups()
4563
- else
4564
- model.openMcpGroups()
4565
- })
4566
- _$insert(_el$6,()=>model.icons.icon("sections"),_el$7)
4567
- _$effect((_$p)=>_$setProp(_el$6,"fg",model.theme().accent,_$p))
4568
- return _el$6
4569
- }}),_el$8)
4570
- _$insertNode(_el$8,_el$9)
4571
- _$setProp(_el$8,"onMouseDown",(event)=>event.stopPropagation())
4572
- _$setProp(_el$8,"onMouseUp",(event)=>{event.stopPropagation()
4573
- model.openLimitPrompt(section())
4574
- })
4575
- _$insert(_el$8,()=>model.icons.icon("todo"),_el$9)
4576
- _$insert(_el$8,()=>props.preferences.selectedSectionItemLimit?.(section())||"All",null)
4577
- _$setProp(_el$0,"onMouseDown",(event)=>{event.stopPropagation()
4578
- model.reorder(props.option.value,-1)
4579
- })
4580
- _$insert(_el$0,()=>model.icons.icon("up"))
4581
- _$setProp(_el$1,"onMouseDown",(event)=>{event.stopPropagation()
4582
- model.reorder(props.option.value,1)
4583
- })
4584
- _$insert(_el$1,()=>model.icons.icon("down"))
4585
- _$effect((_p$)=>{var _v$3=model.theme().accent,_v$4=model.theme().accent,_v$5=model.theme().accent
4586
- _v$3!==_p$.e&&(_p$.e=_$setProp(_el$8,"fg",_v$3,_p$.e))
4587
- _v$4!==_p$.t&&(_p$.t=_$setProp(_el$0,"fg",_v$4,_p$.t))
4588
- _v$5!==_p$.a&&(_p$.a=_$setProp(_el$1,"fg",_v$5,_p$.a))
4589
- return _p$
4590
- },{e:undefined,t:undefined,a:undefined
4591
- })
4592
- return _el$3
4593
- }})]
4594
- }})
4595
- }
4596
- function SettingsDialog(props){const model=createSettingsDialogController(props)
4597
- return _$createComponent(DialogSurface,{get api(){return props.api
4598
- },get children(){return [(()=>{var _el$=_$createElement("box"),_el$2=_$createElement("text"),_el$3=_$createTextNode(` Navigator settings`),_el$4=_$createElement("text")
4599
- _$insertNode(_el$,_el$2)
4600
- _$insertNode(_el$,_el$4)
4601
- _$setProp(_el$,"flexDirection","row")
4602
- _$setProp(_el$,"justifyContent","space-between")
4603
- _$insertNode(_el$2,_el$3)
4604
- _$insert(_el$2,()=>model.icons.icon("settings"),_el$3)
4605
- _$setProp(_el$4,"onMouseDown",(event)=>event.stopPropagation())
4606
- _$setProp(_el$4,"onMouseUp",(event)=>{event.stopPropagation()
4607
- model.dialogs.back()
4608
- })
4609
- _$insert(_el$4,()=>model.icons.key("esc"))
4610
- _$effect((_p$)=>{var _v$=TextAttributes16.BOLD,_v$2=model.theme().text,_v$3=model.theme().textMuted
4611
- _v$!==_p$.e&&(_p$.e=_$setProp(_el$2,"attributes",_v$,_p$.e))
4612
- _v$2!==_p$.t&&(_p$.t=_$setProp(_el$2,"fg",_v$2,_p$.t))
4613
- _v$3!==_p$.a&&(_p$.a=_$setProp(_el$4,"fg",_v$3,_p$.a))
4614
- return _p$
4615
- },{e:undefined,t:undefined,a:undefined
4616
- })
4617
- return _el$
4618
- })(),(()=>{var _el$5=_$createElement("text")
4619
- _$insertNode(_el$5,_$createTextNode(`Adjust sections and behavior. Changes apply immediately.`))
4620
- _$effect((_$p)=>_$setProp(_el$5,"fg",model.theme().textMuted,_$p))
4621
- return _el$5
4622
- })(),(()=>{var _el$7=_$createElement("box")
4623
- _$setProp(_el$7,"flexDirection","row")
4624
- _$setProp(_el$7,"gap",1)
4625
- _$insert(_el$7,_$createComponent(For10,{get each(){return model.orderedGroups()
4626
- },children:(group)=>_$createComponent(Tab,{get api(){return props.api
4627
- },get selected(){return model.activeGroup()===group.id
4628
- },paddingLeft:1,paddingRight:1,onMouseDown:()=>{model.setActiveGroup(group.id)
4629
- model.setActive(0)
4630
- },get children(){return [_$memo(()=>model.icons.tab(group.id))," ",_$memo(()=>group.tab)]
4631
- }})
4632
- }))
4633
- return _el$7
4634
- })(),(()=>{var _el$8=_$createElement("scrollbox"),_el$9=_$createElement("box")
4635
- _$insertNode(_el$8,_el$9)
4636
- var _ref$=model.setBody
4637
- typeof _ref$==="function"?_$use(_ref$,_el$8):model.setBody=_el$8
4638
- _$setProp(_el$8,"id",`${PLUGIN_ID}.settings.body`)
4639
- _$setProp(_el$8,"scrollX",false)
4640
- _$setProp(_el$8,"verticalScrollbarOptions",{visible:true
4641
- })
4642
- _$setProp(_el$8,"horizontalScrollbarOptions",{visible:false
4643
- })
4644
- _$setProp(_el$9,"gap",1)
4645
- _$insert(_el$9,_$createComponent(For10,{get each(){return model.options()
4646
- },children:(option)=>_$createComponent(SettingsOptionRow,{get preferences(){return props.preferences
4647
- },controller:model,option
4648
- })
4649
- }))
4650
- _$effect((_p$)=>{var{restoreScroll:_v$4,saveScroll:_v$5}=model,_v$6=model.contentHeight()
4651
- _v$4!==_p$.e&&(_p$.e=_$setProp(_el$8,"renderBefore",_v$4,_p$.e))
4652
- _v$5!==_p$.t&&(_p$.t=_$setProp(_el$8,"renderAfter",_v$5,_p$.t))
4653
- _v$6!==_p$.a&&(_p$.a=_$setProp(_el$8,"height",_v$6,_p$.a))
4654
- return _p$
4655
- },{e:undefined,t:undefined,a:undefined
4656
- })
4657
- return _el$8
4658
- })(),(()=>{var _el$0=_$createElement("text")
4659
- _$insert(_el$0,()=>model.footerHint())
4660
- _$effect((_$p)=>_$setProp(_el$0,"fg",model.theme().textMuted,_$p))
4661
- return _el$0
4662
- })()]
4663
- }})
4664
- }
4665
- function openSettings(api,preferences,activeValue,mcp,skills){createDialogStack(api,preferences.lspIconStyle,()=>true,preferences.cornerFont).open(()=>_$createComponent(SettingsDialog,{api,preferences,mcp,skills,activeValue
4666
- }),"xlarge")
4276
+ })
4277
+ onCleanup12(unregister)
4278
+ return _$createElement("box")
4667
4279
  }
4668
4280
 
4669
4281
 
4670
- 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)
4671
- }],bindings:[{key:{name:",",ctrl:true
4672
- },cmd:`${PLUGIN_ID}.settings`
4673
- }]
4674
- })
4675
- onCleanup12(unregister)
4676
- return _$createElement("box")
4677
- }
4678
-
4679
-
4680
- function currentPermissionMode(api){const title=api.keymap.getCommands?.({visibility:"registered"
4681
- }).find((command)=>command.name==="permission.mode")?.title
4682
- if(typeof title!=="string")
4683
- return
4684
- if(title.startsWith("Disable auto-approve permissions"))
4685
- return true
4686
- return title.startsWith("Enable auto-approve permissions")?false:undefined
4687
- }
4688
4282
  function PermissionModeBinding(props){let applying=false
4689
4283
  let observed
4690
- createEffect12(()=>{if(!props.preferences.ready())
4284
+ createEffect11(()=>{if(!props.preferences.ready())
4691
4285
  return
4692
4286
  const preferred=props.preferences.autoApprovePermissions()
4693
4287
  const current=currentPermissionMode(props.api)
@@ -4714,15 +4308,109 @@ return _$createElement("box")
4714
4308
 
4715
4309
 
4716
4310
 
4717
- function SettingsFooterButton(props){const icons=useIcons()
4718
- const [hovered,setHovered]=createSignal16(false)
4719
- const theme=()=>props.api.theme.current
4720
- return _$createComponent(IconControl,{id:`${PLUGIN_ID}.settings.footer`,get icon(){return icons.icon("settings")
4721
- },get foregroundColor(){return _$memo(()=>!!hovered())()?theme().text:theme().textMuted
4722
- },get backgroundColor(){return _$memo(()=>!!hovered())()?theme().backgroundElement:theme().backgroundPanel
4723
- },onMouseOver:()=>setHovered(true),onMouseOut:()=>setHovered(false),onMouseUp:()=>openSettings(props.api,props.preferences,undefined,props.mcp,props.skills)
4724
- })
4725
- }
4311
+ function SettingsFooterButton(props){const icons=useIcons()
4312
+ const [hovered,setHovered]=createSignal15(false)
4313
+ const theme=()=>props.api.theme.current
4314
+ return _$createComponent(IconControl,{id:`${PLUGIN_ID}.settings.footer`,get icon(){return icons.icon("settings")
4315
+ },get foregroundColor(){return _$memo(()=>!!hovered())()?theme().text:theme().textMuted
4316
+ },get backgroundColor(){return _$memo(()=>!!hovered())()?theme().backgroundElement:theme().backgroundPanel
4317
+ },onMouseOver:()=>setHovered(true),onMouseOut:()=>setHovered(false),onMouseUp:()=>openSettings(props.api,props.preferences,undefined,props.mcp,props.skills)
4318
+ })
4319
+ }
4320
+
4321
+
4322
+
4323
+ var ACTIONS=[{key:"h",label:"Toggle sidebar",icon:"sections",group:"navigate",command:"session.sidebar.toggle",section:undefined
4324
+ },{key:"t",label:"Todo",icon:"todo",group:"navigate",command:`${PLUGIN_ID}.focus.todo`,section:"todo"},{key:"a",label:"Subagents",icon:"subagents",group:"navigate",command:`${PLUGIN_ID}.focus.subagents`,section:"subagents"
4325
+ },{key:"s",label:"Skills",icon:"skills",group:"navigate",command:`${PLUGIN_ID}.focus.skills`,section:"skills"
4326
+ },{key:"q",label:"Quick actions",icon:"actions",group:"navigate",command:`${PLUGIN_ID}.focus.quick_actions`,section:"quick_actions"
4327
+ },{key:"l",label:"LSP",icon:"lsp",group:"navigate",command:`${PLUGIN_ID}.focus.lsp`,section:"lsp"},{key:"m",label:"MCP",icon:"mcp",group:"navigate",command:`${PLUGIN_ID}.focus.mcp`,section:"mcp"},{key:"c",label:"Check update",icon:"search",group:"updates",command:`${PLUGIN_ID}.check-update`,section:undefined
4328
+ },{key:"u",label:"Update Navigator",icon:"update",group:"updates",command:`${PLUGIN_ID}.update-navigator`,section:undefined
4329
+ }]
4330
+ function sidebarShortcutActions(api){return ACTIONS.filter(({section})=>!section||supportsSidebarSection(api,section))
4331
+ }
4332
+ var ENTRY_COMMAND=`${PLUGIN_ID}.sidebar-shortcuts.enter`
4333
+ var CANCEL_COMMAND=`${PLUGIN_ID}.sidebar-shortcuts.cancel`
4334
+ var MODE=`${PLUGIN_ID}.sidebar-shortcuts`
4335
+ var DEFAULT_TIMEOUT_MS=5000
4336
+ function createSidebarShortcutMode(api,options={}){const actions=sidebarShortcutActions(api)
4337
+ const [active,setActive]=createSignal16(false)
4338
+ const timeoutMs=options.timeoutMs??DEFAULT_TIMEOUT_MS
4339
+ let shortcutKey=""
4340
+ let unregisterBinding
4341
+ let unregisterMode
4342
+ let leaveMode
4343
+ let timeout
4344
+ let disposed=false
4345
+ function cancel(){if(timeout)
4346
+ clearTimeout(timeout)
4347
+ timeout=undefined
4348
+ unregisterMode?.()
4349
+ unregisterMode=undefined
4350
+ leaveMode?.()
4351
+ leaveMode=undefined
4352
+ setActive(false)
4353
+ }
4354
+ function run(command){cancel()
4355
+ if(api.route.current.name!=="session"||api.ui?.dialog?.open)
4356
+ return
4357
+ return api.keymap.dispatchCommand(command)
4358
+ }
4359
+ function enter(){if(disposed||api.route.current.name!=="session"||api.ui?.dialog?.open)
4360
+ return false
4361
+ cancel()
4362
+ unregisterMode=api.keymap.registerLayer({mode:MODE,priority:2000,commands:[{name:ENTRY_COMMAND,run:enter},{name:CANCEL_COMMAND,run:cancel},...actions.map(({key,command})=>({name:`${MODE}.${key}`,run:()=>run(command)
4363
+ }))],bindings:[{key:"escape",cmd:CANCEL_COMMAND},{key:shortcutKey,cmd:ENTRY_COMMAND},...actions.map(({key})=>({key,cmd:`${MODE}.${key}`}))]
4364
+ })
4365
+ leaveMode=api.mode.push(MODE)
4366
+ timeout=setTimeout(cancel,timeoutMs)
4367
+ setActive(true)
4368
+ return true
4369
+ }
4370
+ const unregisterCommands=api.keymap.registerLayer({mode:"base",commands:[{name:TOGGLE_COMMAND,title:"Toggle sidebar",category:"Navigator",namespace:"palette",enabled:()=>api.route.current.name==="session"&&!api.ui?.dialog?.open,run:()=>api.keymap.dispatchCommand("session.sidebar.toggle")
4371
+ },{name:`${LEGACY_PLUGIN_ID}.toggle`,run:()=>api.keymap.dispatchCommand("session.sidebar.toggle")
4372
+ },{name:ENTRY_COMMAND,enabled:()=>api.route.current.name==="session"&&!api.ui?.dialog?.open,run:enter
4373
+ }]
4374
+ })
4375
+ return{active,actions,bind(key){cancel()
4376
+ unregisterBinding?.()
4377
+ shortcutKey=key
4378
+ unregisterBinding=api.keymap.registerLayer({mode:"base",bindings:[{key,cmd:ENTRY_COMMAND}]
4379
+ })
4380
+ },enter,cancel,dispose(){disposed=true
4381
+ cancel()
4382
+ unregisterBinding?.()
4383
+ unregisterBinding=undefined
4384
+ unregisterCommands()
4385
+ }}}
4386
+
4387
+ var SidebarShortcutHint=lazy4(()=>{const path=import.meta.url.includes("/dist/tui.js")?"./sidebar-shortcuts.js":"../../../sidebar-shortcuts"
4388
+ return import(path)
4389
+ });
4390
+
4391
+
4392
+
4393
+
4394
+
4395
+
4396
+
4397
+
4398
+
4399
+
4400
+
4401
+
4402
+
4403
+
4404
+
4405
+
4406
+
4407
+
4408
+
4409
+
4410
+
4411
+
4412
+
4413
+
4726
4414
 
4727
4415
 
4728
4416
  import {realpathSync} from "fs"
@@ -4788,14 +4476,14 @@ queueMicrotask(()=>void props.controller.start())
4788
4476
  })
4789
4477
  onCleanup14(unregister)
4790
4478
  } else
4791
- createEffect13(()=>{if(!props.controller.enabled())
4479
+ createEffect12(()=>{if(!props.controller.enabled())
4792
4480
  return
4793
4481
  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()
4794
4482
  }]
4795
4483
  })
4796
4484
  onCleanup14(unregister)
4797
4485
  })
4798
- onMount5(()=>void props.controller.initialize())
4486
+ onMount4(()=>void props.controller.initialize())
4799
4487
  onCleanup14(props.controller.dispose)
4800
4488
  return _$createElement("box")
4801
4489
  }
@@ -4842,7 +4530,7 @@ return Bun.file(new URL("../../../../CHANGELOG.md",import.meta.url)).text()
4842
4530
 
4843
4531
 
4844
4532
 
4845
- function UpgradeNotesDialog(props){const dimensions=useTerminalDimensions7()
4533
+ function UpgradeNotesDialog(props){const dimensions=useTerminalDimensions9()
4846
4534
  const dialogs=useDialogs(props.api)
4847
4535
  const icons=useIcons()
4848
4536
  const theme=()=>props.api.theme.current
@@ -4912,7 +4600,7 @@ return _el$8
4912
4600
  }
4913
4601
  function UpgradeNotesBinding(props){let pending
4914
4602
  let disposed=false
4915
- onMount6(async ()=>{const previous=await props.preferences.claimNavigatorUpgrade(props.version)
4603
+ onMount5(async ()=>{const previous=await props.preferences.claimNavigatorUpgrade(props.version)
4916
4604
  if(!previous||disposed)
4917
4605
  return
4918
4606
  try{let show=function(){if(disposed||props.api.lifecycle.signal?.aborted)
@@ -5362,7 +5050,7 @@ _$setProp(_el$2,"flexShrink",0)
5362
5050
  _$insert(_el$2,()=>lspIcon(props.id,props.iconStyle??icons.style()))
5363
5051
  _$effect((_$p)=>_$setProp(_el$2,"fg",item.foregroundColor(),_$p))
5364
5052
  return _el$2
5365
- })(),_$createComponent(Show7,{get when(){return showName()
5053
+ })(),_$createComponent(Show10,{get when(){return showName()
5366
5054
  },get children(){var _el$3=_$createElement("text")
5367
5055
  _$setProp(_el$3,"flexShrink",0)
5368
5056
  _$setProp(_el$3,"wrapMode","none")
@@ -5383,7 +5071,7 @@ return _el$3
5383
5071
  function createListVisibility(options){const [expanded,setExpanded]=createSignal21(false)
5384
5072
  let previousKey
5385
5073
  let previousLimit
5386
- const canToggle=createMemo10(()=>options.limit()>0&&options.items().length>options.limit())
5074
+ const canToggle=createMemo8(()=>options.limit()>0&&options.items().length>options.limit())
5387
5075
  createComputed(()=>{const key=options.resetKey()
5388
5076
  const limit=options.limit()
5389
5077
  const isToggle=canToggle()
@@ -5392,7 +5080,7 @@ untrack3(()=>setExpanded(false))
5392
5080
  previousKey=key
5393
5081
  previousLimit=limit
5394
5082
  })
5395
- const visible=createMemo10(()=>!canToggle()||expanded()?options.items():options.items().slice(0,options.limit()))
5083
+ const visible=createMemo8(()=>!canToggle()||expanded()?options.items():options.items().slice(0,options.limit()))
5396
5084
  return{visible,expanded,canToggle,hiddenCount:()=>options.items().length-visible().length,showAll:()=>setExpanded(canToggle()),showLess:()=>setExpanded(false)
5397
5085
  }}
5398
5086
 
@@ -5417,7 +5105,7 @@ else
5417
5105
  props.visibility.showAll()
5418
5106
  queueMicrotask(()=>props.interaction?.select(id))
5419
5107
  }})
5420
- return _$createComponent(Show8,{get when(){return props.visibility.canToggle()
5108
+ return _$createComponent(Show11,{get when(){return props.visibility.canToggle()
5421
5109
  },get children(){return _$createComponent(SelectionBox,{ref(r$){var _ref$=item.ref
5422
5110
  typeof _ref$==="function"?_ref$(r$):item.ref=r$
5423
5111
  },id,paddingLeft:1,paddingRight:1,get backgroundColor(){return item.backgroundColor()
@@ -5470,7 +5158,7 @@ return result + ellipsis
5470
5158
  function SectionHeaderControl(props){const [width,setWidth]=createSignal22()
5471
5159
  const control=useSidebarItem(props.api,props.interaction,{id:props.action.id,position:()=>props.position,disabled:props.action.disabled,activate:props.action.onActivate
5472
5160
  },()=>props.api.theme.current.accent,"control")
5473
- createEffect14(on(()=>[props.action.label(),props.resetWidth],()=>setWidth(undefined)))
5161
+ createEffect13(on(()=>[props.action.label(),props.resetWidth],()=>setWidth(undefined)))
5474
5162
  const label=()=>width()===undefined||props.iconOnly?props.action.label():truncateEnd(props.action.label(),width()-2)
5475
5163
  return _$createComponent(SelectionBox,{ref:(node)=>control.ref(node),get id(){return props.action.id
5476
5164
  },get iconOnly(){return props.iconOnly
@@ -5534,7 +5222,7 @@ _$setProp(_el$7,"flexGrow",1)
5534
5222
  _$setProp(_el$7,"minWidth",0)
5535
5223
  _$setProp(_el$7,"justifyContent","flex-end")
5536
5224
  _$insert(_el$7,()=>props.headerControls,null)
5537
- _$insert(_el$7,_$createComponent(Show9,{get when(){return props.headerAction
5225
+ _$insert(_el$7,_$createComponent(Show12,{get when(){return props.headerAction
5538
5226
  },children:(action)=>_$createComponent(SectionHeaderControl,{get api(){return props.api
5539
5227
  },get interaction(){return props.interaction
5540
5228
  },get action(){return action()
@@ -5542,7 +5230,7 @@ _$insert(_el$7,_$createComponent(Show9,{get when(){return props.headerAction
5542
5230
  },get position(){return{section:props.navigationSection??0,row:0,column:1
5543
5231
  }}})
5544
5232
  }),null)
5545
- _$insert(_el$7,_$createComponent(Show9,{get when(){return props.summary
5233
+ _$insert(_el$7,_$createComponent(Show12,{get when(){return props.summary
5546
5234
  },get children(){var _el$8=_$createElement("text")
5547
5235
  _$setProp(_el$8,"wrapMode","none")
5548
5236
  _$setProp(_el$8,"truncate",true)
@@ -5559,25 +5247,25 @@ return _el$8
5559
5247
  return _el$7
5560
5248
  })()]
5561
5249
  }}),null)
5562
- _$insert(_el$,_$createComponent(Show9,{get when(){return props.open
5250
+ _$insert(_el$,_$createComponent(Show12,{get when(){return props.open
5563
5251
  },get children(){return props.children
5564
5252
  }}),null)
5565
5253
  return _el$
5566
5254
  })()
5567
5255
  }
5568
5256
  var SectionWithHeaderAction=Section;
5569
- 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)))
5257
+ function LspSection(props){const list=createMemo9(()=>[...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)))
5570
5258
  const visibility=createListVisibility({items:list,limit:()=>props.preferences.sectionItemLimit?.("lsp")??0,resetKey:()=>currentLocation(props.api).key
5571
5259
  })
5572
- const connected=createMemo11(()=>list().filter((item)=>item.status==="connected").length)
5573
- const disabled=createMemo11(()=>props.api.state.config.lsp===false)
5260
+ const connected=createMemo9(()=>list().filter((item)=>item.status==="connected").length)
5261
+ const disabled=createMemo9(()=>props.api.state.config.lsp===false)
5574
5262
  const navigationSection=()=>props.navigationSection??5
5575
5263
  return _$createComponent(Section,{get api(){return props.api
5576
5264
  },get interaction(){return props.interaction
5577
5265
  },sectionId:`${PLUGIN_ID}.section.lsp`,get navigationSection(){return navigationSection()
5578
5266
  },title:"LSP",section:"lsp",get summary(){return `${connected()}/${list().length}`
5579
5267
  },get open(){return props.preferences.expanded().lsp
5580
- },onToggle:()=>props.preferences.toggleSectionExpanded("lsp"),get children(){return [_$createComponent(Show10,{get when(){return list().length>0
5268
+ },onToggle:()=>props.preferences.toggleSectionExpanded("lsp"),get children(){return [_$createComponent(Show13,{get when(){return list().length>0
5581
5269
  },get fallback(){return(()=>{var _el$2=_$createElement("text")
5582
5270
  _$insert(_el$2,()=>disabled()?"LSP is disabled":"Activates as files are read")
5583
5271
  _$effect((_$p)=>_$setProp(_el$2,"fg",props.api.theme.current.textMuted,_$p))
@@ -5609,25 +5297,25 @@ return _el$
5609
5297
 
5610
5298
 
5611
5299
 
5612
- function createMcpSectionModel(props,query){const target=createMemo12(()=>props.controller.target())
5613
- const favorites=createMemo12(()=>props.preferences.favoriteMcpServers?.()??new Set)
5614
- const groups=createMemo12(()=>props.preferences.mcpServerGroups?.()??{})
5615
- const grouped=createMemo12(()=>Object.keys(groups()).length>0)
5616
- const list=createMemo12(()=>buildMcpGroupedView(props.controller.list(target()),favorites(),groups()))
5300
+ function createMcpSectionModel(props,query){const target=createMemo10(()=>props.controller.target())
5301
+ const favorites=createMemo10(()=>props.preferences.favoriteMcpServers?.()??new Set)
5302
+ const groups=createMemo10(()=>props.preferences.mcpServerGroups?.()??{})
5303
+ const grouped=createMemo10(()=>Object.keys(groups()).length>0)
5304
+ const list=createMemo10(()=>buildMcpGroupedView(props.controller.list(target()),favorites(),groups()))
5617
5305
  const groupItems=(bucket)=>list().filter((item)=>item.bucket===bucket)
5618
- const filtered=createMemo12(()=>list().filter((item)=>matchesFilter(query(),`${item.name} ${item.assignedGroup ?? ""}`)))
5306
+ const filtered=createMemo10(()=>list().filter((item)=>matchesFilter(query(),`${item.name} ${item.assignedGroup ?? ""}`)))
5619
5307
  const visibility=createListVisibility({items:filtered,limit:()=>props.preferences.sectionItemLimit?.("mcp")??0,resetKey:()=>JSON.stringify([target().key,query()])
5620
5308
  })
5621
- const active=createMemo12(()=>list().filter((item)=>item.status==="connected").length)
5622
- const state=createMemo12(()=>props.controller.state(target()))
5623
- const bulk=createMemo12(()=>props.controller.bulkState?.(target())??{action:"connect",status:"idle",completed:0,total:0,failed:[]
5309
+ const active=createMemo10(()=>list().filter((item)=>item.status==="connected").length)
5310
+ const state=createMemo10(()=>props.controller.state(target()))
5311
+ const bulk=createMemo10(()=>props.controller.bulkState?.(target())??{action:"connect",status:"idle",completed:0,total:0,failed:[]
5624
5312
  })
5625
- const bulkRunning=createMemo12(()=>bulk().status==="running")
5626
- const mutationRunning=createMemo12(()=>props.controller.mutating?.(target()))
5627
- const connectable=createMemo12(()=>list().filter((item)=>mcpToggleAction2(item.status)==="connect").length)
5628
- const disconnectable=createMemo12(()=>list().filter((item)=>mcpToggleAction2(item.status)==="disconnect").length)
5629
- const errors=createMemo12(()=>list().filter((item)=>item.status==="failed"||item.status==="needs_auth"||item.status==="needs_client_registration").length)
5630
- const presetName=createMemo12(()=>{const presets=props.preferences.mcpPresets?.()??{}
5313
+ const bulkRunning=createMemo10(()=>bulk().status==="running")
5314
+ const mutationRunning=createMemo10(()=>props.controller.mutating?.(target()))
5315
+ const connectable=createMemo10(()=>list().filter((item)=>mcpToggleAction2(item.status)==="connect").length)
5316
+ const disconnectable=createMemo10(()=>list().filter((item)=>mcpToggleAction2(item.status)==="disconnect").length)
5317
+ const errors=createMemo10(()=>list().filter((item)=>item.status==="failed"||item.status==="needs_auth"||item.status==="needs_client_registration").length)
5318
+ const presetName=createMemo10(()=>{const presets=props.preferences.mcpPresets?.()??{}
5631
5319
  const selected=props.controller.selectedPreset?.(target())
5632
5320
  return selected&&Object.hasOwn(presets,selected)?selected:matchingMcpPreset(list(),presets)
5633
5321
  })
@@ -5702,7 +5390,7 @@ _$insert(_el$,_$createComponent(McpBulkAction,{get api(){return props.api
5702
5390
  }),null)
5703
5391
  _$effect((_$p)=>_$setProp(_el$,"paddingBottom",model.bulkRunning()||model.bulk().status==="error"?1:0,_$p))
5704
5392
  return _el$
5705
- })(),_$createComponent(Show11,{get when(){return model.bulkRunning()
5393
+ })(),_$createComponent(Show14,{get when(){return model.bulkRunning()
5706
5394
  },get children(){var _el$2=_$createElement("text"),_el$3=_$createTextNode(` `),_el$4=_$createTextNode(`/`),_el$5=_$createTextNode(`\u2026`)
5707
5395
  _$insertNode(_el$2,_el$3)
5708
5396
  _$insertNode(_el$2,_el$4)
@@ -5712,7 +5400,7 @@ _$insert(_el$2,()=>model.bulk().completed,_el$4)
5712
5400
  _$insert(_el$2,()=>model.bulk().total,_el$5)
5713
5401
  _$effect((_$p)=>_$setProp(_el$2,"fg",props.api.theme.current.textMuted,_$p))
5714
5402
  return _el$2
5715
- }}),_$createComponent(Show11,{get when(){return model.bulk().status==="error"
5403
+ }}),_$createComponent(Show14,{get when(){return model.bulk().status==="error"
5716
5404
  },get children(){return _$createComponent(McpBulkAction,{get api(){return props.api
5717
5405
  },get interaction(){return props.interaction
5718
5406
  },id:`${PLUGIN_ID}.mcp.retry-all`,get position(){return{section:props.navigationSection,row:3,column:0
@@ -5792,7 +5480,7 @@ return _el$4
5792
5480
  function RequestErrorRow(props){const icons=useIcons()
5793
5481
  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
5794
5482
  })
5795
- return _$createComponent(Show12,{get when(){return props.state.error
5483
+ return _$createComponent(Show15,{get when(){return props.state.error
5796
5484
  },children:(error)=>_$createComponent(SelectionBox,{ref:(node)=>item.ref(node),get id(){return props.id
5797
5485
  },flexDirection:"row",gap:1,paddingLeft:1,paddingRight:1,get backgroundColor(){return item.backgroundColor()
5798
5486
  },get onMouseOver(){return item.onMouseOver
@@ -5807,7 +5495,7 @@ _$insert(_el$,()=>icons.icon("error"),_el$2)
5807
5495
  _$insert(_el$,()=>error().message,null)
5808
5496
  _$effect((_$p)=>_$setProp(_el$,"fg",item.focused()?item.foregroundColor():props.api.theme.current.error,_$p))
5809
5497
  return _el$
5810
- })(),_$createComponent(Show12,{get when(){return error().retryable
5498
+ })(),_$createComponent(Show15,{get when(){return error().retryable
5811
5499
  },get children(){var _el$3=_$createElement("text"),_el$4=_$createTextNode(` Retry`)
5812
5500
  _$insertNode(_el$3,_el$4)
5813
5501
  _$setProp(_el$3,"flexShrink",0)
@@ -5822,7 +5510,7 @@ function SectionRequestBody(props){const icons=useIcons()
5822
5510
  const pending=()=>props.state.status==="loading"
5823
5511
  return(()=>{var _el$5=_$createElement("box")
5824
5512
  _$insert(_el$5,_$createComponent(RequestErrorRow,props),null)
5825
- _$insert(_el$5,_$createComponent(Show12,{get when(){return _$memo(()=>!!pending())()&&!props.hasItems
5513
+ _$insert(_el$5,_$createComponent(Show15,{get when(){return _$memo(()=>!!pending())()&&!props.hasItems
5826
5514
  },get children(){var _el$6=_$createElement("text"),_el$7=_$createTextNode(` `)
5827
5515
  _$insertNode(_el$6,_el$7)
5828
5516
  _$insert(_el$6,()=>icons.icon("pending"),_el$7)
@@ -5830,10 +5518,10 @@ _$insert(_el$6,()=>props.loading,null)
5830
5518
  _$effect((_$p)=>_$setProp(_el$6,"fg",props.api.theme.current.textMuted,_$p))
5831
5519
  return _el$6
5832
5520
  }}),null)
5833
- _$insert(_el$5,_$createComponent(Show12,{get when(){return props.hasItems
5521
+ _$insert(_el$5,_$createComponent(Show15,{get when(){return props.hasItems
5834
5522
  },get children(){return props.children
5835
5523
  }}),null)
5836
- _$insert(_el$5,_$createComponent(Show12,{get when(){return _$memo(()=>!!((props.state.status==="ready"||props.state.status==="refreshing")&&!props.hasItems))()&&!props.state.error
5524
+ _$insert(_el$5,_$createComponent(Show15,{get when(){return _$memo(()=>!!((props.state.status==="ready"||props.state.status==="refreshing")&&!props.hasItems))()&&!props.state.error
5837
5525
  },get children(){var _el$8=_$createElement("text"),_el$9=_$createTextNode(` `)
5838
5526
  _$insertNode(_el$8,_el$9)
5839
5527
  _$insert(_el$8,()=>icons.icon("info"),_el$9)
@@ -6026,7 +5714,7 @@ return _p$
6026
5714
  },{e:undefined,t:undefined,a:undefined,o:undefined,i:undefined,n:undefined,s:undefined,h:undefined
6027
5715
  })
6028
5716
  return _el$2
6029
- })(),_$createComponent(Show13,{get when(){return props.query
5717
+ })(),_$createComponent(Show16,{get when(){return props.query
6030
5718
  },get children(){var _el$3=_$createElement("text")
6031
5719
  _$setProp(_el$3,"flexShrink",0)
6032
5720
  _$setProp(_el$3,"onMouseDown",()=>props.onInput(""))
@@ -6055,7 +5743,7 @@ _$insert(_el$,_$createComponent(SectionFilter,{get api(){return props.api
6055
5743
  }},get query(){return props.query
6056
5744
  },placeholder:"Filter MCP...",get onInput(){return props.onQuery
6057
5745
  }}),null)
6058
- _$insert(_el$,_$createComponent(Show14,{get when(){return model.filtered().length>0
5746
+ _$insert(_el$,_$createComponent(Show17,{get when(){return model.filtered().length>0
6059
5747
  },get fallback(){return(()=>{var _el$2=_$createElement("text")
6060
5748
  _$insertNode(_el$2,_$createTextNode(`No matching MCP servers`))
6061
5749
  _$effect((_$p)=>_$setProp(_el$2,"fg",props.api.theme.current.textMuted,_$p))
@@ -6066,7 +5754,7 @@ return _el$2
6066
5754
  },get grouped(){return model.grouped
6067
5755
  },get density(){return props.preferences.rowDensity?.()??"compact"
6068
5756
  },get children(){return _$createComponent(For13,{get each(){return model.visibility.visible()
6069
- },children:(item,index)=>[_$createComponent(Show14,{get when(){return _$memo(()=>!!model.grouped())()&&(index()===0||model.visibility.visible()[index()-1]?.bucket!==item.bucket)
5757
+ },children:(item,index)=>[_$createComponent(Show17,{get when(){return _$memo(()=>!!model.grouped())()&&(index()===0||model.visibility.visible()[index()-1]?.bucket!==item.bucket)
6070
5758
  },get children(){return _$createComponent(McpGroupHeader,{get api(){return props.api
6071
5759
  },get interaction(){return props.interaction
6072
5760
  },get bucket(){return item.bucket
@@ -6100,7 +5788,7 @@ function McpSection(props){const icons=useIcons()
6100
5788
  const [query,setQuery]=createSignal26("")
6101
5789
  const model=createMcpSectionModel(props,query)
6102
5790
  const navigationSection=()=>props.navigationSection??6
6103
- const summary=createMemo13(()=>`${model.active()}/${model.list().length}${model.errors() ? ` \xB7 ${model.errors()} ${icons.icon("error")}` : ""}`)
5791
+ const summary=createMemo11(()=>`${model.active()}/${model.list().length}${model.errors() ? ` \xB7 ${model.errors()} ${icons.icon("error")}` : ""}`)
6104
5792
  return _$createComponent(SectionWithHeaderAction,{get api(){return props.api
6105
5793
  },get interaction(){return props.interaction
6106
5794
  },sectionId:`${PLUGIN_ID}.section.mcp`,get navigationSection(){return navigationSection()
@@ -6198,17 +5886,51 @@ return _$createComponent(SectionWithHeaderAction,{get api(){return props.api
6198
5886
 
6199
5887
 
6200
5888
 
5889
+
5890
+
5891
+ var ToolbarContext=createContext4()
5892
+ var useToolbar=()=>useContext4(ToolbarContext)
5893
+ function ToolbarProvider(props){const value={pinned:(pin)=>Boolean(props.preferences.toolbarPins?.().some((item)=>toolbarPinKey(item)===toolbarPinKey(pin))),configure:(pin,dialogs)=>{if(pin.kind==="skill"&&!pin.location){props.api.ui.toast({variant:"warning",title:"Toolbar",message:"This Skill has no host-provided source location"
5894
+ })
5895
+ return
5896
+ }
5897
+ openToolbarPin({api:props.api,preferences:props.preferences,skills:props.skills,pin,dialogs
5898
+ })
5899
+ }}
5900
+ return _$createComponent(ToolbarContext.Provider,{value,get children(){return props.children
5901
+ }})
5902
+ }
5903
+
5904
+ function SidebarPinControl(props){const toolbar=useToolbar()
5905
+ const{api,interaction
5906
+ }=useSidebarList()
5907
+ const icons=useIcons()
5908
+ const item=useSidebarItem(api,interaction,{id:`${props.id}.pin`,position:()=>({...props.position,column:2
5909
+ }),activate:()=>toolbar?.configure(props.pin)
5910
+ },()=>toolbar?.pinned(props.pin)?api.theme.current.accent:api.theme.current.textMuted,"control")
5911
+ return _$createComponent(IconControl,{get id(){return `${props.id}.pin`
5912
+ },ref(r$){var _ref$=item.ref
5913
+ typeof _ref$==="function"?_ref$(r$):item.ref=r$
5914
+ },get icon(){return terminalIcon("pin",icons.style())
5915
+ },get backgroundColor(){return item.backgroundColor()
5916
+ },get foregroundColor(){return item.foregroundColor()
5917
+ },get onMouseOver(){return item.onMouseOver
5918
+ },get onMouseOut(){return item.onMouseOut
5919
+ },onMouseUp:(event)=>item.activate(event)
5920
+ })
5921
+ }
6201
5922
  function QuickActionRow(props){const{api,interaction
6202
5923
  }=useSidebarList()
6203
5924
  const icons=useIcons()
5925
+ const toolbar=useToolbar()
6204
5926
  const theme=()=>api.theme.current
6205
5927
  const [width,setWidth]=createSignal30(0)
6206
- const shortcut=createMemo14(()=>{const bindings=api.keymap.getCommandBindings({visibility:"registered",commands:[props.action.command]
5928
+ const shortcut=createMemo12(()=>{const bindings=api.keymap.getCommandBindings({visibility:"registered",commands:[props.action.command]
6207
5929
  })
6208
5930
  return api.keys.formatBindings(bindings.get(props.action.command))
6209
5931
  })
6210
- const visibleShortcut=createMemo14(()=>{const value=shortcut()
6211
- return value&&width()>=Bun.stringWidth(props.action.label) + Bun.stringWidth(value) + 8?value:undefined
5932
+ const visibleShortcut=createMemo12(()=>{const value=shortcut()
5933
+ return value&&width()>=Bun.stringWidth(props.action.label) + Bun.stringWidth(value) + (toolbar?11:8)?value:undefined
6212
5934
  })
6213
5935
  function run(){if(props.action.command==="session.new"&&props.onNewSession?.())
6214
5936
  return
@@ -6246,7 +5968,7 @@ _$insert(_el$2,()=>props.action.label)
6246
5968
  _$effect((_$p)=>_$setProp(_el$2,"fg",row.foregroundColor(),_$p))
6247
5969
  return _el$2
6248
5970
  })()
6249
- },get metadata(){return _$createComponent(Show21,{get when(){return visibleShortcut()
5971
+ },get metadata(){return _$createComponent(Show24,{get when(){return visibleShortcut()
6250
5972
  },children:(value)=>(()=>{var _el$3=_$createElement("text")
6251
5973
  _$setProp(_el$3,"flexShrink",0)
6252
5974
  _$setProp(_el$3,"wrapMode","none")
@@ -6255,7 +5977,12 @@ _$effect((_$p)=>_$setProp(_el$3,"fg",row.focused()?row.foregroundColor():theme()
6255
5977
  return _el$3
6256
5978
  })()
6257
5979
  })
6258
- },get details(){return _$createComponent(Show21,{get when(){return props.disabled
5980
+ },get trailing(){return _$createComponent(Show24,{when:toolbar,get children(){return _$createComponent(SidebarPinControl,{get id(){return id()
5981
+ },get position(){return props.position
5982
+ },get pin(){return{kind:"action",id:props.action.command,icon:"bolt"
5983
+ }}})
5984
+ }})
5985
+ },get details(){return _$createComponent(Show24,{get when(){return props.disabled
6259
5986
  },children:(reason)=>(()=>{var _el$4=_$createElement("text")
6260
5987
  _$setProp(_el$4,"wrapMode","word")
6261
5988
  _$insert(_el$4,reason)
@@ -6266,7 +5993,7 @@ return _el$4
6266
5993
  }})
6267
5994
  }
6268
5995
  function QuickActionsSection(props){const commandRevision=createQuickActionRevision(props.api)
6269
- const actions=createMemo15(()=>{commandRevision()
5996
+ const actions=createMemo13(()=>{commandRevision()
6270
5997
  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)
6271
5998
  return action&&props.preferences.quickActionVisible?.(id)!==false?[{...action,label:quickActionLabel(props.api,action),disabled:quickActionDisabledReason(props.api,action)
6272
5999
  }]:[]
@@ -6283,7 +6010,7 @@ return _$createComponent(Section,{get api(){return props.api
6283
6010
  },onToggle:()=>props.preferences.toggleSectionExpanded("quick_actions"),get children(){return [_$createComponent(SidebarRowList,{get api(){return props.api
6284
6011
  },get interaction(){return props.interaction
6285
6012
  },get density(){return props.preferences.rowDensity?.()??"compact"
6286
- },get children(){return [_$createComponent(Show22,{get when(){return actions().length===0
6013
+ },get children(){return [_$createComponent(Show25,{get when(){return actions().length===0
6287
6014
  },get children(){var _el$=_$createElement("text")
6288
6015
  _$insertNode(_el$,_$createTextNode(`No quick actions selected`))
6289
6016
  _$effect((_$p)=>_$setProp(_el$,"fg",props.api.theme.current.textMuted,_$p))
@@ -6344,63 +6071,33 @@ item.activate(event)
6344
6071
  }
6345
6072
 
6346
6073
 
6347
- var ENTRY_COMMAND=`${PLUGIN_ID}.sidebar-shortcuts.enter`
6348
- var CANCEL_COMMAND=`${PLUGIN_ID}.sidebar-shortcuts.cancel`
6349
- var MODE=`${PLUGIN_ID}.sidebar-shortcuts`
6350
- var DEFAULT_TIMEOUT_MS=5000
6351
- var ACTIONS=[{key:"h",hint:"toggle",command:"session.sidebar.toggle",section:undefined},{key:"t",hint:"todo",command:`${PLUGIN_ID}.focus.todo`,section:"todo"},{key:"a",hint:"agents",command:`${PLUGIN_ID}.focus.subagents`,section:"subagents"},{key:"s",hint:"skills",command:`${PLUGIN_ID}.focus.skills`,section:"skills"},{key:"q",hint:"actions",command:`${PLUGIN_ID}.focus.quick_actions`,section:"quick_actions"},{key:"l",hint:"LSP",command:`${PLUGIN_ID}.focus.lsp`,section:"lsp"},{key:"m",hint:"MCP",command:`${PLUGIN_ID}.focus.mcp`,section:"mcp"},{key:"c",hint:"check update",command:`${PLUGIN_ID}.check-update`,section:undefined},{key:"u",hint:"update",command:`${PLUGIN_ID}.update-navigator`,section:undefined}]
6352
- function createSidebarShortcutMode(api,options={}){const actions=ACTIONS.filter(({section})=>!section||supportsSidebarSection(api,section))
6353
- const hints=actions.map(({key,hint})=>`${key} ${hint}`).join(" | ")
6354
- const timeoutMs=options.timeoutMs??DEFAULT_TIMEOUT_MS
6355
- let shortcutKey=""
6356
- let unregisterBinding
6357
- let unregisterMode
6358
- let leaveMode
6359
- let timeout
6360
- let disposed=false
6361
- function cancel(){if(timeout)
6362
- clearTimeout(timeout)
6363
- timeout=undefined
6364
- unregisterMode?.()
6365
- unregisterMode=undefined
6366
- leaveMode?.()
6367
- leaveMode=undefined
6368
- }
6369
- function run(command){cancel()
6370
- return api.keymap.dispatchCommand(command)
6371
- }
6372
- function enter(){if(disposed||api.route.current.name!=="session"||api.ui?.dialog?.open)
6373
- return false
6374
- cancel()
6375
- unregisterMode=api.keymap.registerLayer({mode:MODE,priority:2000,commands:[{name:ENTRY_COMMAND,run:enter},{name:CANCEL_COMMAND,run:cancel},...actions.map(({key,command})=>({name:`${MODE}.${key}`,run:()=>run(command)
6376
- }))],bindings:[{key:"escape",cmd:CANCEL_COMMAND},{key:shortcutKey,cmd:ENTRY_COMMAND},...actions.map(({key})=>({key,cmd:`${MODE}.${key}`}))]
6377
- })
6378
- leaveMode=api.mode.push(MODE)
6379
- timeout=setTimeout(cancel,timeoutMs)
6380
- api.ui?.toast?.({variant:"info",title:"Navigator shortcuts",message:`${hints} | Esc cancel`,duration:timeoutMs
6381
- })
6382
- return true
6383
- }
6384
- const unregisterCommands=api.keymap.registerLayer({mode:"base",commands:[{name:TOGGLE_COMMAND,title:"Toggle sidebar",category:"Navigator",namespace:"palette",enabled:()=>api.route.current.name==="session"&&!api.ui?.dialog?.open,run:()=>api.keymap.dispatchCommand("session.sidebar.toggle")
6385
- },{name:`${LEGACY_PLUGIN_ID}.toggle`,run:()=>api.keymap.dispatchCommand("session.sidebar.toggle")
6386
- },{name:ENTRY_COMMAND,enabled:()=>api.route.current.name==="session"&&!api.ui?.dialog?.open,run:enter
6387
- }]
6074
+
6075
+
6076
+
6077
+
6078
+ function SidebarToggleBinding(props){const shortcuts=createSidebarShortcutMode(props.api)
6079
+ createEffect15(()=>{const key=props.preferences.toggleKey()
6080
+ untrack6(()=>shortcuts.bind(key))
6388
6081
  })
6389
- return{active:()=>leaveMode!==undefined,bind(key){cancel()
6390
- unregisterBinding?.()
6391
- shortcutKey=key
6392
- unregisterBinding=api.keymap.registerLayer({mode:"base",bindings:[{key,cmd:ENTRY_COMMAND}]
6082
+ createEffect15(()=>{if(shortcuts.active()&&(props.api.route.current.name!=="session"||props.api.ui.dialog.open||props.api.mode.current()==="modal"))
6083
+ untrack6(shortcuts.cancel)
6393
6084
  })
6394
- },enter,cancel,dispose(){disposed=true
6395
- cancel()
6396
- unregisterBinding?.()
6397
- unregisterBinding=undefined
6398
- unregisterCommands()
6399
- }}}
6400
- function SidebarToggleBinding(props){const shortcuts=createSidebarShortcutMode(props.api)
6401
- createEffect16(()=>shortcuts.bind(props.preferences.toggleKey()))
6402
6085
  onCleanup18(shortcuts.dispose)
6403
- return _$createElement("box")
6086
+ return(()=>{var _el$=_$createElement("box")
6087
+ _$setProp(_el$,"position","absolute")
6088
+ _$setProp(_el$,"top",0)
6089
+ _$setProp(_el$,"left",0)
6090
+ _$setProp(_el$,"width","100%")
6091
+ _$setProp(_el$,"height","100%")
6092
+ _$insert(_el$,_$createComponent(Show26,{get when(){return shortcuts.active()
6093
+ },get children(){return _$createComponent(Suspense4,{get children(){return _$createComponent(SidebarShortcutHint,{get api(){return props.api
6094
+ },get actions(){return shortcuts.actions
6095
+ }})
6096
+ }})
6097
+ }}))
6098
+ _$effect((_$p)=>_$setProp(_el$,"visible",shortcuts.active(),_$p))
6099
+ return _el$
6100
+ })()
6404
6101
  }
6405
6102
  function SidebarFocusBinding(props){const commands=props.interaction.baseCommands()
6406
6103
  const unregisterCommands=props.api.keymap.registerLayer({commands:[...commands,...commands.map(({name,run,enabled
@@ -6408,7 +6105,7 @@ const unregisterCommands=props.api.keymap.registerLayer({commands:[...commands,.
6408
6105
  }))]
6409
6106
  })
6410
6107
  onCleanup18(unregisterCommands)
6411
- createEffect16(()=>{const unregister=props.api.keymap.registerLayer({bindings:[{key:props.preferences.focusKey(),cmd:FOCUS_COMMAND
6108
+ createEffect15(()=>{const unregister=props.api.keymap.registerLayer({bindings:[{key:props.preferences.focusKey(),cmd:FOCUS_COMMAND
6412
6109
  }]
6413
6110
  })
6414
6111
  onCleanup18(unregister)
@@ -6431,6 +6128,154 @@ return _$createElement("box")
6431
6128
 
6432
6129
 
6433
6130
 
6131
+ function toolbarLayout(keys,width,mode){const columns=Math.max(1,Math.floor((Math.max(3,width) + 1) / 4))
6132
+ const shown=mode==="wrap"||keys.length<=columns?keys.length:Math.max(0,columns-1)
6133
+ const visible=keys.slice(0,shown)
6134
+ const overflow=keys.slice(shown)
6135
+ const controls=[...visible,...overflow.length>0?["toolbar:more"]:[]]
6136
+ return{columns,overflow,rows:Array.from({length:Math.ceil(controls.length / columns)},(_,row)=>controls.slice(row*columns,(row + 1)*columns))
6137
+ }}
6138
+
6139
+ function createToolbarModel(props){const icons=useIcons()
6140
+ const revision=createQuickActionRevision(props.api)
6141
+ const pins=()=>props.preferences.toolbarPins?.()??[]
6142
+ const needsSkills=createMemo14(()=>pins().some((pin)=>pin.kind==="skill"))
6143
+ const target=createMemo14(()=>props.skills.target())
6144
+ createEffect16(()=>{if(!needsSkills())
6145
+ return
6146
+ const current=target()
6147
+ const release=untrack7(()=>props.skills.activate(current))
6148
+ onCleanup19(release)
6149
+ untrack7(()=>{props.skills.refresh(current).catch(()=>{})
6150
+ })
6151
+ })
6152
+ function view(pin){revision()
6153
+ if(pin.kind==="action"){const action=QUICK_ACTIONS.find((item)=>item.command===pin.id)
6154
+ const state=quickActionState(props.api,pin.id)
6155
+ const stateLabel=quickActionStates(props.api,pin.id).find((item)=>item.id===state)?.label
6156
+ return{label:quickActionLabel(props.api,action),stateLabel,icon:state?pin.stateIcons?.[state]??pin.icon:pin.icon,reason:quickActionDisabledReason(props.api,action)
6157
+ }}
6158
+ const skill=props.skills.list(target()).find((item)=>item.location===pin.location&&item.name===pin.name)
6159
+ const request=props.skills.state(target())
6160
+ const unavailable=request.status==="loading"?"Loading Skills":"Skill is unavailable in this workspace"
6161
+ return{label:pin.name,icon:pin.icon,stateLabel:undefined,reason:request.error?.message??(skill?skillUnavailable(props.skills,skill):unavailable)
6162
+ }}
6163
+ function run(key){const pin=pins().find((item)=>toolbarPinKey(item)===key)
6164
+ if(!pin)
6165
+ return
6166
+ const item=view(pin)
6167
+ if(item.reason){props.api.ui.toast({variant:"warning",title:item.label,message:item.reason})
6168
+ return
6169
+ }
6170
+ if(pin.kind==="action"){if(pin.id==="session.new"&&props.onNewSession?.())
6171
+ return
6172
+ const result=props.interaction.dispatchFromReturnTarget(pin.id)
6173
+ if(!result.ok)
6174
+ props.api.ui.toast({variant:"warning",title:item.label,message:`Command is ${result.reason}`})
6175
+ return
6176
+ }
6177
+ const skill=props.skills.list(target()).find((candidate)=>candidate.location===pin.location&&candidate.name===pin.name)
6178
+ if(!skill)
6179
+ return
6180
+ const route=JSON.stringify(props.api.route.current)
6181
+ const dialogs=createDialogStack(props.api,icons.style,()=>route===JSON.stringify(props.api.route.current),icons.multilineCorners)
6182
+ activateSkill({api:props.api,controller:props.skills,access:props.preferences,skill,dialogs})
6183
+ }
6184
+ return{pins,view,run}}
6185
+
6186
+
6187
+
6188
+ function ToolbarButton(props){const icons=useIcons()
6189
+ const [hovered,setHovered]=createSignal31(false)
6190
+ const item=useSidebarItem(props.api,props.interaction,{id:props.id,position:()=>({section:0,row:props.row + 1,column:props.column
6191
+ }),activate:props.onRun
6192
+ },()=>props.reason?props.api.theme.current.textMuted:props.api.theme.current.accent,"control")
6193
+ createEffect17(()=>props.onDetails(props.id,item.focused()||hovered()))
6194
+ onCleanup20(()=>props.onDetails(props.id,false))
6195
+ return _$createComponent(IconControl,{get id(){return props.id
6196
+ },ref(r$){var _ref$=item.ref
6197
+ typeof _ref$==="function"?_ref$(r$):item.ref=r$
6198
+ },get icon(){return terminalIcon(props.icon,icons.style())
6199
+ },get backgroundColor(){return item.backgroundColor()
6200
+ },get foregroundColor(){return _$memo(()=>!!props.reason)()?props.api.theme.current.textMuted:item.foregroundColor()
6201
+ },onMouseOver:()=>{item.onMouseOver()
6202
+ setHovered(true)
6203
+ },onMouseOut:()=>{item.onMouseOut()
6204
+ setHovered(false)
6205
+ },onMouseUp:(event)=>item.activate(event)
6206
+ })
6207
+ }
6208
+ function SidebarToolbar(props){const model=createToolbarModel(props)
6209
+ const icons=useIcons()
6210
+ const [width,setWidth]=createSignal32(3)
6211
+ const [detail,setDetail]=createSignal32()
6212
+ const keys=createMemo15(()=>model.pins().map((pin)=>toolbarPinKey(pin)))
6213
+ const layout=createMemo15(()=>toolbarLayout(keys(),width(),props.preferences.toolbarOverflow?.()??"menu"))
6214
+ const rows=createMemo15(()=>layout().rows.map((_,index)=>index))
6215
+ const byKey=createMemo15(()=>new Map(model.pins().map((pin)=>[toolbarPinKey(pin),pin])))
6216
+ const view=(key)=>{const pin=byKey().get(key)
6217
+ return pin&&model.view(pin)
6218
+ }
6219
+ const details=createMemo15(()=>{if(detail()==="toolbar:more")
6220
+ return "More pinned actions and Skills"
6221
+ const item=view(detail()??"")
6222
+ return item?[item.label,item.stateLabel,item.reason].filter(Boolean).join(" \xB7 "):undefined
6223
+ })
6224
+ function showMore(){const route=JSON.stringify(props.api.route.current)
6225
+ const dialogs=createDialogStack(props.api,icons.style,()=>route===JSON.stringify(props.api.route.current),icons.multilineCorners)
6226
+ dialogs.open(()=>_$createComponent(SelectionMenu,{get api(){return props.api
6227
+ },title:"More pinned buttons",height:16,get options(){return layout().overflow.flatMap((key)=>{const item=view(key)
6228
+ return item?[{title:item.label,value:key,description:item.reason??item.stateLabel??"Run pinned item"
6229
+ }]:[]
6230
+ })
6231
+ },onSelect:(option)=>{if(view(option.value)?.reason){model.run(option.value)
6232
+ return
6233
+ }
6234
+ dialogs.close()
6235
+ model.run(option.value)
6236
+ }}))
6237
+ }
6238
+ return _$createComponent(Show27,{get when(){return keys().length>0
6239
+ },get children(){var _el$=_$createElement("box")
6240
+ _$setProp(_el$,"id","opencode-navigator.toolbar")
6241
+ _$setProp(_el$,"onSizeChange",function(){setWidth(this.width)
6242
+ })
6243
+ _$insert(_el$,_$createComponent(For17,{get each(){return rows()
6244
+ },children:(row)=>(()=>{var _el$2=_$createElement("box")
6245
+ _$setProp(_el$2,"flexDirection","row")
6246
+ _$setProp(_el$2,"gap",1)
6247
+ _$insert(_el$2,_$createComponent(For17,{get each(){return layout().rows[row]
6248
+ },children:(key,column)=>_$createComponent(ToolbarButton,_$mergeProps(props,{id:`opencode-navigator.toolbar.${key}`,row,get column(){return column()
6249
+ },get label(){return view(key)?.label??"More"
6250
+ },get icon(){return key==="toolbar:more"?"list":view(key)?.icon??"bolt"
6251
+ },get reason(){return view(key)?.reason
6252
+ },onRun:()=>key==="toolbar:more"?showMore():model.run(key),onDetails:(_id,active)=>setDetail((current)=>active?key:current===key?undefined:current)
6253
+ }))
6254
+ }))
6255
+ return _el$2
6256
+ })()
6257
+ }),null)
6258
+ _$insert(_el$,_$createComponent(Show27,{get when(){return details()
6259
+ },children:(text)=>(()=>{var _el$3=_$createElement("text")
6260
+ _$setProp(_el$3,"height",1)
6261
+ _$setProp(_el$3,"truncate",true)
6262
+ _$setProp(_el$3,"wrapMode","none")
6263
+ _$insert(_el$3,text)
6264
+ _$effect((_$p)=>_$setProp(_el$3,"fg",props.api.theme.current.textMuted,_$p))
6265
+ return _el$3
6266
+ })()
6267
+ }),null)
6268
+ return _el$
6269
+ }})
6270
+ }
6271
+
6272
+
6273
+
6274
+
6275
+
6276
+
6277
+
6278
+
6434
6279
 
6435
6280
 
6436
6281
  function createSkillSectionModel(props,query){const target=createMemo16(()=>props.controller.target())
@@ -6442,10 +6287,10 @@ const filtered=createMemo16(()=>list().filter((item)=>matchesFilter(query(),item
6442
6287
  const visibility=createListVisibility({items:filtered,limit:()=>props.preferences.sectionItemLimit?.("skills")??0,resetKey:()=>JSON.stringify([target().key,query()])
6443
6288
  })
6444
6289
  const state=createMemo16(()=>props.controller.state(target()))
6445
- createEffect17(()=>{const current=target()
6446
- const deactivate=untrack6(()=>props.controller.activate?.(current)??(()=>{}))
6447
- onCleanup19(deactivate)
6448
- untrack6(()=>void props.controller.refresh(current).catch(()=>{}))
6290
+ createEffect18(()=>{const current=target()
6291
+ const deactivate=untrack8(()=>props.controller.activate?.(current)??(()=>{}))
6292
+ onCleanup21(deactivate)
6293
+ untrack8(()=>void props.controller.refresh(current).catch(()=>{}))
6449
6294
  })
6450
6295
  async function useSkill(item){try{const isInserted=await props.controller.use(target(),item.name)
6451
6296
  if(isInserted)
@@ -6468,9 +6313,11 @@ return{target,recent,grouped,list,filtered,visibility,state,useSkill,skillGroup}
6468
6313
 
6469
6314
 
6470
6315
 
6316
+
6471
6317
  function SkillRow(props){const{api,interaction,grouped
6472
6318
  }=useSidebarList()
6473
6319
  const icons=useIcons()
6320
+ const toolbar=useToolbar()
6474
6321
  const id=()=>`${PLUGIN_ID}.skill.${props.item.location || props.item.name}`
6475
6322
  const row=useSidebarItem(api,interaction,{id:id(),position:()=>({...props.position,column:1
6476
6323
  }),activate:props.onUse
@@ -6494,24 +6341,21 @@ _$insert(_el$,()=>props.item.name,null)
6494
6341
  _$effect((_$p)=>_$setProp(_el$,"fg",row.foregroundColor(),_$p))
6495
6342
  return _el$
6496
6343
  })()
6344
+ },get trailing(){return _$createComponent(Show28,{when:toolbar,get children(){return _$createComponent(SidebarPinControl,{get id(){return id()
6345
+ },get position(){return props.position
6346
+ },get pin(){return{kind:"skill",name:props.item.name,location:props.item.location,icon:"book"
6347
+ }}})
6348
+ }})
6497
6349
  }})
6498
6350
  }
6499
6351
  function SkillsSection(props){const dialogs=useDialogs(props.api)
6500
- const [query,setQuery]=createSignal31("")
6352
+ const toolbar=useToolbar()
6353
+ const [query,setQuery]=createSignal33("")
6501
6354
  const model=createSkillSectionModel(props,query)
6502
6355
  const navigationSection=()=>props.navigationSection??3
6503
- function selectSkill(item){if(!props.preferences.shouldConfirmSkill(item)){model.useSkill(item)
6504
- return
6505
- }
6506
- showSkillDetails(item)
6507
- }
6508
- function showSkillDetails(item){dialogs.open(()=>_$createComponent(SkillDialog,{get api(){return props.api
6509
- },skill:item,get favorite(){return props.preferences.isFavoriteSkill?.(item)??false
6510
- },get favoriteDisabled(){return props.preferences.ready?.()===false
6511
- },onToggleFavorite:()=>props.preferences.toggleFavoriteSkill?.(item),onAccept:(skipConfirmation)=>{if(skipConfirmation)
6512
- props.preferences.skipSkillConfirmation(item)
6513
- model.useSkill(item)
6514
- }}))
6356
+ function selectSkill(item){activateSkill({api:props.api,controller:props.controller,access:props.preferences,dialogs,skill:item,onConfigure:toolbar?(navigation)=>toolbar.configure({kind:"skill",name:item.name,location:item.location,icon:"book"
6357
+ },navigation):undefined
6358
+ })
6515
6359
  }
6516
6360
  return _$createComponent(Section,{get api(){return props.api
6517
6361
  },get interaction(){return props.interaction
@@ -6530,7 +6374,7 @@ _$insert(_el$,_$createComponent(SectionFilter,{get api(){return props.api
6530
6374
  }},get query(){return query()
6531
6375
  },placeholder:"Filter skills...",onInput:setQuery
6532
6376
  }),null)
6533
- _$insert(_el$,_$createComponent(Show23,{get when(){return model.filtered().length>0
6377
+ _$insert(_el$,_$createComponent(Show29,{get when(){return model.filtered().length>0
6534
6378
  },get fallback(){return(()=>{var _el$2=_$createElement("text")
6535
6379
  _$insertNode(_el$2,_$createTextNode(`No matching skills`))
6536
6380
  _$effect((_$p)=>_$setProp(_el$2,"fg",props.api.theme.current.textMuted,_$p))
@@ -6540,8 +6384,8 @@ return _el$2
6540
6384
  },get interaction(){return props.interaction
6541
6385
  },get grouped(){return model.grouped
6542
6386
  },get density(){return props.preferences.rowDensity?.()??"compact"
6543
- },get children(){return _$createComponent(For17,{get each(){return model.visibility.visible()
6544
- },children:(item,index)=>[_$createComponent(Show23,{get when(){return _$memo(()=>!!model.grouped())()&&(index()===0||model.visibility.visible()[index()-1]?.bucket!==item.bucket)
6387
+ },get children(){return _$createComponent(For18,{get each(){return model.visibility.visible()
6388
+ },children:(item,index)=>[_$createComponent(Show29,{get when(){return _$memo(()=>!!model.grouped())()&&(index()===0||model.visibility.visible()[index()-1]?.bucket!==item.bucket)
6545
6389
  },get children(){var _el$4=_$createElement("text")
6546
6390
  _$setProp(_el$4,"height",1)
6547
6391
  _$setProp(_el$4,"wrapMode","none")
@@ -6586,18 +6430,18 @@ return _el$
6586
6430
  function createSubagentSectionModel(props){const list=createMemo17(()=>props.controller.list(props.sessionID))
6587
6431
  const recent=createMemo17(()=>props.controller.recent?.(props.sessionID)??[])
6588
6432
  const rows=createMemo17(()=>buildSubagentView(list(),recent()))
6589
- const [query,setQuery]=createSignal32("")
6590
- const [mode,setMode]=createSignal32("all")
6433
+ const [query,setQuery]=createSignal34("")
6434
+ const [mode,setMode]=createSignal34("all")
6591
6435
  const counts=createMemo17(()=>countSubagentView(rows(),query()))
6592
6436
  const tabs=createMemo17(()=>["all","active","recent",...counts().errors>0?["errors"]:[]])
6593
6437
  const filtered=createMemo17(()=>filterSubagentView(rows(),mode(),query()))
6594
6438
  const parentID=createMemo17(()=>props.api.state?.session?.get(props.sessionID)?.parentID)
6595
6439
  const targetKey=createMemo17(()=>props.controller.target?.(props.sessionID).key??props.sessionID)
6596
- createEffect18(()=>{targetKey()
6440
+ createEffect19(()=>{targetKey()
6597
6441
  setQuery("")
6598
6442
  setMode("all")
6599
6443
  })
6600
- createEffect18(()=>{if(mode()!=="all"&&counts()[mode()]===0)
6444
+ createEffect19(()=>{if(mode()!=="all"&&counts()[mode()]===0)
6601
6445
  setMode("all")
6602
6446
  })
6603
6447
  const visibility=createListVisibility({items:filtered,limit:()=>props.preferences.sectionItemLimit?.("subagents")??0,resetKey:()=>JSON.stringify([targetKey(),query(),mode()])
@@ -6607,11 +6451,11 @@ const now=createSubagentClock(clockKey)
6607
6451
  const byId=createMemo17(()=>new Map(visibility.visible().map((item)=>[item.session.id,item])))
6608
6452
  const ids=createMemo17(()=>visibility.visible().map((item)=>item.session.id))
6609
6453
  const state=createMemo17(()=>props.controller.state(props.sessionID))
6610
- createEffect18(()=>{const sessionID=props.sessionID
6454
+ createEffect19(()=>{const sessionID=props.sessionID
6611
6455
  targetKey()
6612
- const deactivate=untrack7(()=>props.controller.activate?.(sessionID)??(()=>{}))
6613
- onCleanup20(deactivate)
6614
- untrack7(()=>void props.controller.refresh(sessionID).catch(()=>{}))
6456
+ const deactivate=untrack9(()=>props.controller.activate?.(sessionID)??(()=>{}))
6457
+ onCleanup22(deactivate)
6458
+ untrack9(()=>void props.controller.refresh(sessionID).catch(()=>{}))
6615
6459
  })
6616
6460
  return{list,recent,rows,query,setQuery,mode,setMode,counts,tabs,filtered,parentID,visibility,now,byId,ids,state
6617
6461
  }}
@@ -6668,7 +6512,7 @@ return()=>_c$()?`${props.item.run.startedBeforeObservation ? `${icons.icon("rece
6668
6512
  _$effect((_$p)=>_$setProp(_el$3,"fg",row.focused()?row.foregroundColor():theme().textMuted,_$p))
6669
6513
  return _el$3
6670
6514
  })()
6671
- },get details(){return [_$createComponent(Show24,{get when(){return props.item.run?.errorMessage
6515
+ },get details(){return [_$createComponent(Show30,{get when(){return props.item.run?.errorMessage
6672
6516
  },get children(){var _el$4=_$createElement("text"),_el$5=_$createTextNode(`: `)
6673
6517
  _$insertNode(_el$4,_el$5)
6674
6518
  _$setProp(_el$4,"wrapMode","word")
@@ -6676,12 +6520,12 @@ _$insert(_el$4,()=>cancelled()?"Cancelled":"Error",_el$5)
6676
6520
  _$insert(_el$4,()=>props.item.run?.errorMessage,null)
6677
6521
  _$effect((_$p)=>_$setProp(_el$4,"fg",row.focused()?row.foregroundColor():failed()?theme().error:theme().textMuted,_$p))
6678
6522
  return _el$4
6679
- }}),_$createComponent(Show24,{get when(){return props.item.unavailable
6523
+ }}),_$createComponent(Show30,{get when(){return props.item.unavailable
6680
6524
  },get children(){var _el$6=_$createElement("text")
6681
6525
  _$insertNode(_el$6,_$createTextNode(`Worker status unavailable`))
6682
6526
  _$effect((_$p)=>_$setProp(_el$6,"fg",theme().warning,_$p))
6683
6527
  return _el$6
6684
- }}),_$createComponent(Show24,{get when(){return _$memo(()=>props.item.status.type==="retry")()?props.item.status:undefined
6528
+ }}),_$createComponent(Show30,{get when(){return _$memo(()=>props.item.status.type==="retry")()?props.item.status:undefined
6685
6529
  },children:(status)=>(()=>{var _el$0=_$createElement("text"),_el$1=_$createTextNode(`Retry #`),_el$10=_$createTextNode(` \xB7 `),_el$11=_$createTextNode(`s \xB7 `)
6686
6530
  _$insertNode(_el$0,_el$1)
6687
6531
  _$insertNode(_el$0,_el$10)
@@ -6693,7 +6537,7 @@ _$insert(_el$0,()=>status().message,null)
6693
6537
  _$effect((_$p)=>_$setProp(_el$0,"fg",row.focused()?row.foregroundColor():theme().warning,_$p))
6694
6538
  return _el$0
6695
6539
  })()
6696
- }),_$createComponent(Show24,{get when(){return _$memo(()=>!!idle())()&&!props.item.run?.errorMessage
6540
+ }),_$createComponent(Show30,{get when(){return _$memo(()=>!!idle())()&&!props.item.run?.errorMessage
6697
6541
  },get children(){var _el$8=_$createElement("text")
6698
6542
  _$insertNode(_el$8,_$createTextNode(`Finished`))
6699
6543
  _$effect((_$p)=>_$setProp(_el$8,"fg",theme().textMuted,_$p))
@@ -6704,12 +6548,12 @@ return _el$8
6704
6548
  function SubagentList(props){return _$createComponent(SidebarRowList,{get api(){return props.api
6705
6549
  },get interaction(){return props.interaction
6706
6550
  },get density(){return props.density
6707
- },get children(){return _$createComponent(For18,{get each(){return props.ids
6551
+ },get children(){return _$createComponent(For19,{get each(){return props.ids
6708
6552
  },children:(id,index)=>{const initial=props.itemById(id)
6709
6553
  const item=()=>props.itemById(id)??initial
6710
6554
  const startsGroup=()=>index()===0||props.visible[index()-1]?.group!==item().group
6711
6555
  return(()=>{var _el$=_$createElement("box")
6712
- _$insert(_el$,_$createComponent(Show25,{get when(){return startsGroup()
6556
+ _$insert(_el$,_$createComponent(Show31,{get when(){return startsGroup()
6713
6557
  },get children(){var _el$2=_$createElement("text"),_el$3=_$createElement("b")
6714
6558
  _$insertNode(_el$2,_el$3)
6715
6559
  _$insert(_el$3,()=>item().group)
@@ -6735,7 +6579,7 @@ return _$createComponent(Section,{get api(){return props.api
6735
6579
  },sectionId:`${PLUGIN_ID}.section.subagents`,get navigationSection(){return navigationSection()
6736
6580
  },title:"SUBAGENTS",section:"subagents",get summary(){return `${model.list().length} active \xB7 ${model.recent().length} recent`
6737
6581
  },get open(){return props.preferences.expanded().subagents
6738
- },onToggle:()=>props.preferences.toggleSectionExpanded("subagents"),get children(){return [_$createComponent(Show26,{get when(){return model.parentID()
6582
+ },onToggle:()=>props.preferences.toggleSectionExpanded("subagents"),get children(){return [_$createComponent(Show32,{get when(){return model.parentID()
6739
6583
  },children:(id)=>_$createComponent(McpBulkAction,{get api(){return props.api
6740
6584
  },get interaction(){return props.interaction
6741
6585
  },id:`${PLUGIN_ID}.subagents.parent`,get position(){return{section:navigationSection(),row:1,column:0
@@ -6758,7 +6602,7 @@ _$insert(_el$,_$createComponent(SectionFilter,{get api(){return props.api
6758
6602
  }}),_el$2)
6759
6603
  _$setProp(_el$2,"flexDirection","row")
6760
6604
  _$setProp(_el$2,"flexWrap","wrap")
6761
- _$insert(_el$2,_$createComponent(For19,{get each(){return model.tabs()
6605
+ _$insert(_el$2,_$createComponent(For20,{get each(){return model.tabs()
6762
6606
  },children:(value,index)=>_$createComponent(SectionTab,{get api(){return props.api
6763
6607
  },get interaction(){return props.interaction
6764
6608
  },id:`${PLUGIN_ID}.subagents.filter.${value}`,get position(){return{section:navigationSection(),row:4,column:index()
@@ -6769,7 +6613,7 @@ _$insert(_el$2,_$createComponent(For19,{get each(){return model.tabs()
6769
6613
  },onActivate:()=>model.setMode(value)
6770
6614
  })
6771
6615
  }))
6772
- _$insert(_el$,_$createComponent(Show26,{get when(){return model.filtered().length===0
6616
+ _$insert(_el$,_$createComponent(Show32,{get when(){return model.filtered().length===0
6773
6617
  },get children(){var _el$3=_$createElement("text")
6774
6618
  _$insertNode(_el$3,_$createTextNode(`No matching subagents`))
6775
6619
  _$effect((_$p)=>_$setProp(_el$3,"fg",props.api.theme.current.textMuted,_$p))
@@ -6810,6 +6654,23 @@ return _el$
6810
6654
 
6811
6655
 
6812
6656
 
6657
+ function NativeTodoNotice(props){const icons=useIcons()
6658
+ return(()=>{var _el$=_$createElement("text"),_el$2=_$createTextNode(` Native OpenCode Todo. Edit tasks through chat and todowrite.`)
6659
+ _$insertNode(_el$,_el$2)
6660
+ _$setProp(_el$,"wrapMode","word")
6661
+ _$insert(_el$,()=>icons.icon("info"),_el$2)
6662
+ _$insert(_el$,()=>props.empty?" OpenCode 2.1 enables the tool through experimental.todo.":"",null)
6663
+ _$effect((_$p)=>_$setProp(_el$,"fg",props.api.theme.current.textMuted,_$p))
6664
+ return _el$
6665
+ })()
6666
+ }
6667
+
6668
+
6669
+
6670
+
6671
+
6672
+
6673
+
6813
6674
 
6814
6675
 
6815
6676
 
@@ -6853,7 +6714,7 @@ _$insert(_el$2,()=>icons.icon(done()?"done":active()?"busy":cancelled()?"close":
6853
6714
  _$setProp(_el$3,"flexGrow",1)
6854
6715
  _$setProp(_el$3,"wrapMode","word")
6855
6716
  _$insert(_el$3,()=>props.item.content)
6856
- _$insert(_el$,_$createComponent(Show27,{get when(){return props.item.priority==="high"||props.item.priority==="medium"||props.item.priority==="low"
6717
+ _$insert(_el$,_$createComponent(Show33,{get when(){return props.item.priority==="high"||props.item.priority==="medium"||props.item.priority==="low"
6857
6718
  },get children(){var _el$4=_$createElement("text"),_el$5=_$createElement("b"),_el$6=_$createTextNode(` `)
6858
6719
  _$insertNode(_el$4,_el$5)
6859
6720
  _$setProp(_el$4,"width",2)
@@ -6880,7 +6741,7 @@ _$insertNode(_el$,_el$2)
6880
6741
  _$setProp(_el$,"gap",1)
6881
6742
  _$setProp(_el$2,"flexDirection","row")
6882
6743
  _$setProp(_el$2,"flexWrap","wrap")
6883
- _$insert(_el$2,_$createComponent(For20,{each:["all","active","finished"],children:(value,index)=>_$createComponent(SectionTab,{get api(){return props.api
6744
+ _$insert(_el$2,_$createComponent(For21,{each:["all","active","finished"],children:(value,index)=>_$createComponent(SectionTab,{get api(){return props.api
6884
6745
  },get interaction(){return props.interaction
6885
6746
  },id:`${PLUGIN_ID}.todo.filter.${value}`,get position(){return{section:navigationSection(),row:tabsRow(),column:index()
6886
6747
  }},get label(){return value[0].toUpperCase() + value.slice(1)
@@ -6889,17 +6750,17 @@ _$insert(_el$2,_$createComponent(For20,{each:["all","active","finished"],childre
6889
6750
  },onActivate:()=>props.setMode(value)
6890
6751
  })
6891
6752
  }))
6892
- _$insert(_el$,_$createComponent(Show28,{get when(){return props.view.rows.length>0
6753
+ _$insert(_el$,_$createComponent(Show34,{get when(){return props.view.rows.length>0
6893
6754
  },get fallback(){return _$createComponent(EmptyTodo,{get api(){return props.api
6894
6755
  },get mode(){return props.mode
6895
6756
  }})
6896
6757
  },get children(){return _$createComponent(SidebarRowList,{get api(){return props.api
6897
6758
  },get interaction(){return props.interaction
6898
6759
  },get density(){return props.density
6899
- },get children(){return _$createComponent(For20,{get each(){return props.visibility.visible()
6760
+ },get children(){return _$createComponent(For21,{get each(){return props.visibility.visible()
6900
6761
  },children:(row,index)=>{const startsGroup=()=>index()===0||props.visibility.visible()[index()-1].group!==row.group
6901
6762
  return(()=>{var _el$3=_$createElement("box")
6902
- _$insert(_el$3,_$createComponent(Show28,{get when(){return startsGroup()
6763
+ _$insert(_el$3,_$createComponent(Show34,{get when(){return startsGroup()
6903
6764
  },get children(){var _el$4=_$createElement("text"),_el$5=_$createElement("b")
6904
6765
  _$insertNode(_el$4,_el$5)
6905
6766
  _$insert(_el$5,()=>row.group)
@@ -6936,7 +6797,7 @@ return _el$6
6936
6797
 
6937
6798
 
6938
6799
  function TodoGuidanceControl(props){const state=()=>props.controller.guidance(props.sessionID)
6939
- return _$createComponent(Show29,{get when(){return state().available
6800
+ return _$createComponent(Show35,{get when(){return state().available
6940
6801
  },get children(){var _el$=_$createElement("box")
6941
6802
  _$insert(_el$,_$createComponent(SectionTab,{get api(){return props.api
6942
6803
  },get interaction(){return props.interaction
@@ -6946,7 +6807,7 @@ _$insert(_el$,_$createComponent(SectionTab,{get api(){return props.api
6946
6807
  },get disabled(){return state().saving
6947
6808
  },onActivate:()=>void props.controller.setGuidance(props.sessionID,!state().enabled)
6948
6809
  }),null)
6949
- _$insert(_el$,_$createComponent(Show29,{get when(){return state().error
6810
+ _$insert(_el$,_$createComponent(Show35,{get when(){return state().error
6950
6811
  },children:(message)=>(()=>{var _el$2=_$createElement("text")
6951
6812
  _$setProp(_el$2,"wrapMode","word")
6952
6813
  _$insert(_el$2,message)
@@ -6961,33 +6822,41 @@ function TodoSection(props){const list=createMemo18(()=>props.controller.list(pr
6961
6822
  const icons=useIcons()
6962
6823
  const unavailable=()=>hostCapabilityUnavailable(props.api,"todo")
6963
6824
  const managed=()=>("guidance" in props.controller)?props.controller:undefined
6964
- const [mode,setMode]=createSignal33("all")
6825
+ const native=()=>("source" in props.controller)&&props.controller.source==="native"
6826
+ const [mode,setMode]=createSignal35("all")
6965
6827
  const targetKey=createMemo18(()=>props.controller.target?.(props.sessionID).key??props.sessionID)
6966
- createEffect19(()=>{targetKey()
6828
+ createEffect20(()=>{targetKey()
6967
6829
  setMode("all")
6968
6830
  })
6969
6831
  const view=createMemo18(()=>buildTodoView(list(),mode()))
6970
6832
  const visibility=createListVisibility({items:()=>view().rows,limit:()=>props.preferences.sectionItemLimit?.("todo")??0,resetKey:()=>JSON.stringify([targetKey(),mode()])
6971
6833
  })
6972
6834
  const state=createMemo18(()=>props.controller.state(props.sessionID))
6973
- createEffect19(()=>{const sessionID=props.sessionID
6835
+ createEffect20(()=>{const sessionID=props.sessionID
6974
6836
  targetKey()
6975
6837
  if(unavailable())
6976
6838
  return
6977
- const deactivate=untrack8(()=>props.controller.activate?.(sessionID)??(()=>{}))
6978
- onCleanup21(deactivate)
6979
- untrack8(()=>void props.controller.refresh(sessionID).catch(()=>{}))
6839
+ const deactivate=untrack10(()=>props.controller.activate?.(sessionID)??(()=>{}))
6840
+ onCleanup23(deactivate)
6841
+ untrack10(()=>void props.controller.refresh(sessionID).catch(()=>{}))
6980
6842
  })
6981
6843
  const navigationSection=()=>props.navigationSection??1
6982
6844
  return _$createComponent(Section,{get api(){return props.api
6983
6845
  },get interaction(){return props.interaction
6984
6846
  },sectionId:`${PLUGIN_ID}.section.todo`,get navigationSection(){return navigationSection()
6985
6847
  },title:"TODO",section:"todo",get summary(){return _$memo(()=>!!(unavailable()||managed()?.missing(props.sessionID)))()?"\u2014":`${view().counts.completed}/${list().length}`
6848
+ },get headerAction(){return native()?{id:`${PLUGIN_ID}.todo.refresh`,label:()=>`${icons.icon("retry")} Refresh`,disabled:()=>state().status==="loading"||state().status==="refreshing",onActivate:()=>{props.controller.refresh(props.sessionID).catch(()=>{})
6849
+ }}:undefined
6986
6850
  },get open(){return props.preferences.expanded().todo
6987
- },onToggle:()=>props.preferences.toggleSectionExpanded("todo"),get children(){return _$createComponent(Show30,{get when(){return unavailable()
6851
+ },onToggle:()=>props.preferences.toggleSectionExpanded("todo"),get children(){return _$createComponent(Show36,{get when(){return unavailable()
6988
6852
  },get fallback(){return(()=>{var _el$=_$createElement("box")
6989
6853
  _$setProp(_el$,"gap",1)
6990
- _$insert(_el$,_$createComponent(Show30,{get when(){return managed()?.guidance(props.sessionID).available
6854
+ _$insert(_el$,_$createComponent(Show36,{get when(){return native()
6855
+ },get children(){return _$createComponent(NativeTodoNotice,{get api(){return props.api
6856
+ },get empty(){return list().length===0
6857
+ }})
6858
+ }}),null)
6859
+ _$insert(_el$,_$createComponent(Show36,{get when(){return managed()?.guidance(props.sessionID).available
6991
6860
  },get children(){return _$createComponent(TodoGuidanceControl,{get api(){return props.api
6992
6861
  },get controller(){return managed()
6993
6862
  },get sessionID(){return props.sessionID
@@ -6995,7 +6864,7 @@ _$insert(_el$,_$createComponent(Show30,{get when(){return managed()?.guidance(pr
6995
6864
  },get navigationSection(){return navigationSection()
6996
6865
  }})
6997
6866
  }}),null)
6998
- _$insert(_el$,_$createComponent(Show30,{get when(){return managed()?.missing(props.sessionID)
6867
+ _$insert(_el$,_$createComponent(Show36,{get when(){return managed()?.missing(props.sessionID)
6999
6868
  },get fallback(){return _$createComponent(SectionRequestBody,{get api(){return props.api
7000
6869
  },get interaction(){return props.interaction
7001
6870
  },id:`${PLUGIN_ID}.retry.todo`,get position(){return{section:navigationSection(),row:1,column:0
@@ -7032,8 +6901,11 @@ return _el$4
7032
6901
  }
7033
6902
  function SidebarContent(props){const sections=props.preferences.sections
7034
6903
  const visibleSections=createMemo19(()=>props.preferences.sectionOrder().filter((section)=>sections()[section]&&supportsSidebarSection(props.api,section)))
7035
- onCleanup22(()=>props.interaction.setContentRoot(undefined))
7036
- return(()=>{var _el$=_$createElement("box")
6904
+ onCleanup24(()=>props.interaction.setContentRoot(undefined))
6905
+ return _$createComponent(ToolbarProvider,{get api(){return props.api
6906
+ },get preferences(){return props.preferences
6907
+ },get skills(){return props.skills
6908
+ },get children(){var _el$=_$createElement("box")
7037
6909
  _$use((node)=>props.interaction.setContentRoot(node),_el$)
7038
6910
  _$setProp(_el$,"id",`${PLUGIN_ID}.root`)
7039
6911
  _$setProp(_el$,"focusable",true)
@@ -7044,7 +6916,8 @@ event.preventDefault()
7044
6916
  event.stopPropagation()
7045
6917
  props.interaction.leave()
7046
6918
  })
7047
- _$insert(_el$,_$createComponent(For21,{get each(){return visibleSections()
6919
+ _$insert(_el$,_$createComponent(SidebarToolbar,props),null)
6920
+ _$insert(_el$,_$createComponent(For22,{get each(){return visibleSections()
7048
6921
  },children:(section,index)=>_$createComponent(SectionBoundary,{get api(){return props.api
7049
6922
  },get divided(){return index()<visibleSections().length-1
7050
6923
  },get children(){return _$createComponent(Switch,{get children(){return [_$createComponent(Match,{when:section==="limits",get children(){return props.limitsSection(index() + 1)
@@ -7067,7 +6940,7 @@ _$insert(_el$,_$createComponent(For21,{get each(){return visibleSections()
7067
6940
  }})]
7068
6941
  }})
7069
6942
  }})
7070
- }))
6943
+ }),null)
7071
6944
  _$effect((_p$)=>{var _v$=props.interaction.syncFocus,_v$2=props.interaction.syncFocus
7072
6945
  _v$!==_p$.e&&(_p$.e=_$setProp(_el$,"on:focused",_v$,_p$.e))
7073
6946
  _v$2!==_p$.t&&(_p$.t=_$setProp(_el$,"on:blurred",_v$2,_p$.t))
@@ -7075,12 +6948,12 @@ return _p$
7075
6948
  },{e:undefined,t:undefined
7076
6949
  })
7077
6950
  return _el$
7078
- })()
6951
+ }})
7079
6952
  }
7080
6953
 
7081
6954
 
7082
6955
  function McpPersistence(props){const persist=createMemo20(()=>props.controller.persist())
7083
- createEffect20(()=>{if(!props.api.state.ready)
6956
+ createEffect21(()=>{if(!props.api.state.ready)
7084
6957
  return
7085
6958
  persist()
7086
6959
  const route=props.api.route.current
@@ -7088,20 +6961,20 @@ const params="params" in route?route.params:undefined
7088
6961
  if(typeof params?.sessionID!=="string")
7089
6962
  return
7090
6963
  const current=props.controller.target()
7091
- onCleanup23(()=>props.controller.deactivate(current))
7092
- untrack9(()=>void props.controller.activate(current).catch(()=>{}))
6964
+ onCleanup25(()=>props.controller.deactivate(current))
6965
+ untrack11(()=>void props.controller.activate(current).catch(()=>{}))
7093
6966
  })
7094
6967
  return _$createElement("box")
7095
6968
  }
7096
- function PreferencesPersistence(props){createEffect20(()=>{const location=currentLocation(props.api)
7097
- untrack9(()=>props.controller.setActiveScope(preferencesScope({directory:location.routing.directory,worktree:props.api.state.path.worktree
6969
+ function PreferencesPersistence(props){createEffect21(()=>{const location=currentLocation(props.api)
6970
+ untrack11(()=>props.controller.setActiveScope(preferencesScope({directory:location.routing.directory,worktree:props.api.state.path.worktree
7098
6971
  })))
7099
6972
  props.controller.load()
7100
6973
  })
7101
6974
  return _$createElement("box")
7102
6975
  }
7103
6976
  function FirstRunWizardPersistence(props){let isChecked=false
7104
- createEffect20(()=>{if(isChecked)
6977
+ createEffect21(()=>{if(isChecked)
7105
6978
  return
7106
6979
  isChecked=true
7107
6980
  showFirstRunWizard(props.api,props.preferences).catch(()=>{})
@@ -7128,7 +7001,7 @@ const settingsId=`${PLUGIN_ID}.settings`
7128
7001
  const settings=useSidebarItem(props.api,props.interaction,{id:settingsId,position:{section:0,row:0,column:0
7129
7002
  },activate:()=>openSettings(props.api,props.preferences,undefined,props.mcp,props.skills)
7130
7003
  },()=>theme().textMuted,"control")
7131
- onCleanup24(()=>props.interaction.setTitleRoot(undefined))
7004
+ onCleanup26(()=>props.interaction.setTitleRoot(undefined))
7132
7005
  return(()=>{var _el$=_$createElement("box"),_el$2=_$createElement("box"),_el$3=_$createElement("box")
7133
7006
  _$insertNode(_el$,_el$2)
7134
7007
  _$use((node)=>props.interaction.setTitleRoot(node),_el$)
@@ -7139,7 +7012,7 @@ _$setProp(_el$2,"flexDirection","row")
7139
7012
  _$setProp(_el$2,"justifyContent","space-between")
7140
7013
  _$setProp(_el$2,"gap",1)
7141
7014
  _$setProp(_el$3,"flexGrow",1)
7142
- _$insert(_el$3,_$createComponent(Show31,{get when(){return props.preferences.showSessionTitle()
7015
+ _$insert(_el$3,_$createComponent(Show37,{get when(){return props.preferences.showSessionTitle()
7143
7016
  },get children(){var _el$4=_$createElement("text"),_el$5=_$createElement("b")
7144
7017
  _$insertNode(_el$4,_el$5)
7145
7018
  _$setProp(_el$4,"wrapMode","word")
@@ -7147,7 +7020,7 @@ _$insert(_el$5,()=>props.title)
7147
7020
  _$effect((_$p)=>_$setProp(_el$4,"fg",theme().text,_$p))
7148
7021
  return _el$4
7149
7022
  }}),null)
7150
- _$insert(_el$3,_$createComponent(Show31,{get when(){return _$memo(()=>!!props.preferences.showSessionDate())()&&created()
7023
+ _$insert(_el$3,_$createComponent(Show37,{get when(){return _$memo(()=>!!props.preferences.showSessionDate())()&&created()
7151
7024
  },children:(value)=>(()=>{var _el$6=_$createElement("text")
7152
7025
  _$insert(_el$6,value)
7153
7026
  _$effect((_$p)=>_$setProp(_el$6,"fg",theme().textMuted,_$p))
@@ -7196,11 +7069,11 @@ function createLimitsRefresh(options,schedule=scheduleInterval){let disposed=fal
7196
7069
  const selectedKey=createMemo22(()=>JSON.stringify(options.selectedModel?.()))
7197
7070
  const targetKey=createMemo22(()=>JSON.stringify(options.controller.current().model))
7198
7071
  const interval=createMemo22(()=>(parseLimitsRefreshMinutes(options.refreshMinutes?.())??DEFAULT_LIMITS_REFRESH_MINUTES)*60000)
7199
- createEffect21(on2(selectedKey,()=>{const model=options.selectedModel?.()
7072
+ createEffect22(on2(selectedKey,()=>{const model=options.selectedModel?.()
7200
7073
  if(model&&options.accountSource)
7201
7074
  options.accountSource.refresh(model).catch(()=>{})
7202
7075
  }))
7203
- createEffect21(on2(targetKey,()=>{const{model,adapter}=options.controller.current()
7076
+ createEffect22(on2(targetKey,()=>{const{model,adapter}=options.controller.current()
7204
7077
  if(model&&adapter)
7205
7078
  options.controller.refresh()
7206
7079
  }))
@@ -7213,9 +7086,9 @@ await options.accountSource.refresh(model)
7213
7086
  if(!disposed&&target===targetKey())
7214
7087
  await options.controller.refresh()
7215
7088
  }
7216
- createEffect21(on2(interval,(milliseconds)=>{onCleanup25(schedule(()=>void refresh().catch(()=>{}),milliseconds))
7089
+ createEffect22(on2(interval,(milliseconds)=>{onCleanup27(schedule(()=>void refresh().catch(()=>{}),milliseconds))
7217
7090
  }))
7218
- onCleanup25(()=>{disposed=true
7091
+ onCleanup27(()=>{disposed=true
7219
7092
  })
7220
7093
  }
7221
7094
  function LimitsPersistence(props){createLimitsRefresh(props)
@@ -7247,9 +7120,24 @@ const data=Object.fromEntries(response.data.map((server)=>[server.name,server.st
7247
7120
  return{data}},async connect(input,options={}){await context.client.mcp.connect({server:input.name,...location(input)},{signal:options.signal})
7248
7121
  return{data:undefined}},async disconnect(input,options={}){await context.client.mcp.disconnect({server:input.name,...location(input)},{signal:options.signal})
7249
7122
  return{data:undefined}}}}}}
7250
- var SESSION_UPDATE_EVENTS=new Set(["session.agent.selected","session.model.selected","session.moved","session.renamed","session.permissions"])
7123
+ var TERMINAL_EVENTS=new Set(["session.execution.succeeded","session.execution.failed","session.execution.interrupted"])
7124
+ function executionStatus(name,event){const sessionID=event.data.sessionID
7125
+ const started=event.type==="session.execution.started"
7126
+ if(typeof sessionID!=="string"||!started&&!TERMINAL_EVENTS.has(event.type))
7127
+ return
7128
+ if(name!=="session.status"&&(name!=="session.idle"||started))
7129
+ return
7130
+ const status=started?{type:"busy"}:{type:"idle"}
7131
+ return{sessionID,status,properties:{sessionID,...name==="session.status"&&{status}}}}
7132
+ var SESSION_UPDATE_EVENTS=new Set(["session.agent.selected","session.model.selected","session.moved","session.renamed","session.permissions","session.metadata.updated"])
7251
7133
  function createV2EventAdapter(context,sessions){return{on(name,handler){let active=true
7252
7134
  const unsubscribe=context.data.listen(({details})=>{const event=details
7135
+ const execution=executionStatus(name,event)
7136
+ if(execution){sessions.setStatus(execution.sessionID,execution.status)
7137
+ handler({type:name,properties:execution.properties
7138
+ })
7139
+ return
7140
+ }
7253
7141
  if(name==="server.connected"&&event.type==="server.connected"){handler({type:name,properties:{}})
7254
7142
  return
7255
7143
  }
@@ -7303,8 +7191,8 @@ unsubscribe()
7303
7191
  }}}}
7304
7192
 
7305
7193
 
7306
- var SETTINGS_COMMAND="opencode.settings"
7307
- var PERMISSIONS_ACTION="permission.mode"
7194
+ function enabled(value){return typeof value==="function"?value():value!==false
7195
+ }
7308
7196
  function belongsTo2(renderable,ancestor){if(!renderable||!ancestor)
7309
7197
  return false
7310
7198
  for(let current=renderable;current; current=current.parent){if(current===ancestor)
@@ -7312,9 +7200,15 @@ return true
7312
7200
  }
7313
7201
  return false
7314
7202
  }
7315
- function enabled(value){return typeof value==="function"?value():value!==false
7203
+ function v2LayerCommands(id,layer,available,run,dispatch){const named=(layer.commands??[]).map((command)=>({id:command.name,bind:command.name==="session.new"?"<leader>n":undefined,title:command.title,description:command.desc,group:command.category,palette:command.namespace==="palette"?true:undefined,suggested:command.suggested,enabled:()=>available()&&enabled(command.enabled),run:(input,event)=>run(command,input,event)
7204
+ }))
7205
+ const bindings=(layer.bindings??[]).flatMap((binding,index)=>typeof binding.key==="string"?[{id:`${PLUGIN_ID}.v2-binding.${id}.${index}`,bind:binding.key,enabled:available,run:()=>dispatch(String(binding.cmd))
7206
+ }]:[])
7207
+ return [...named,...bindings]
7316
7208
  }
7317
- function createV2Keymap(context){const [revision,setRevision]=createSignal34(0)
7209
+ var SETTINGS_COMMAND="opencode.settings"
7210
+ var PERMISSIONS_ACTION="permission.mode"
7211
+ function createV2Keymap(context){const [revision,setRevision]=createSignal36(0)
7318
7212
  const layers=new Map
7319
7213
  let sequence=0
7320
7214
  function layerActive(layer){const mode=layer.mode??"base"
@@ -7338,16 +7232,11 @@ event.stopPropagation()
7338
7232
  runV2(command,"",event)
7339
7233
  }
7340
7234
  context.renderer.keyInput.on("keypress",onKeypress)
7341
- function v2Commands(id,layer){const available=()=>layerActive(layer)
7342
- const named=(layer.commands??[]).map((command)=>({id:command.name,bind:command.name==="session.new"?"<leader>n":undefined,title:command.title,description:command.desc,group:command.category,palette:command.namespace==="palette"?true:undefined,suggested:command.suggested,enabled:()=>available()&&enabled(command.enabled),run:(input,event)=>runV2(command,input,event)
7343
- }))
7344
- const bindings=(layer.bindings??[]).flatMap((binding,index)=>typeof binding.key==="string"?[{id:`${PLUGIN_ID}.v2-binding.${id}.${index}`,bind:binding.key,enabled:available,run:()=>{context.keymap.dispatch(String(binding.cmd))
7345
- }}]:[])
7346
- return [...named,...bindings]
7235
+ function layerCommands([id,layer]){return v2LayerCommands(id,layer,()=>layerActive(layer),runV2,context.keymap.dispatch)
7347
7236
  }
7348
7237
  function Bridge(){context.keymap.layer(()=>{revision()
7349
7238
  const current=[...layers].sort(([leftID,left],[rightID,right])=>(right.priority??0)-(left.priority??0)||rightID-leftID)
7350
- const commands=current.flatMap(([id,layer])=>v2Commands(id,layer))
7239
+ const commands=current.flatMap((entry)=>layerCommands(entry))
7351
7240
  const bindings=commands.flatMap((command)=>command.id?[command.id]:[])
7352
7241
  return{mode:"global",priority:2000,commands,bindings
7353
7242
  }})
@@ -7421,13 +7310,20 @@ return "opencode-navigator"
7421
7310
  }}}
7422
7311
  function legacyTheme(theme){return{primary:theme.hue.interactive[200],secondary:theme.categorical[0]?.[200]??theme.hue.accent[200],accent:theme.hue.accent[200],error:theme.text.feedback.error.base,warning:theme.text.feedback.warning.base,success:theme.text.feedback.success.base,info:theme.text.feedback.info.base,text:theme.text.base,textMuted:theme.text.muted,selectedListItemText:theme.text.action.primary.focused,background:theme.background.base,backgroundPanel:theme.background.raised.base,backgroundElement:theme.background.raised.high,backgroundMenu:theme.background.raised.max,border:theme.border.base,borderActive:theme.scrollbar.base,borderSubtle:theme.hue.neutral[500],diffAdded:theme.diff.text.added,diffRemoved:theme.diff.text.removed,diffContext:theme.diff.text.context,diffHunkHeader:theme.diff.text.hunkHeader,diffHighlightAdded:theme.diff.highlight.added,diffHighlightRemoved:theme.diff.highlight.removed,diffAddedBg:theme.diff.background.added,diffRemovedBg:theme.diff.background.removed,diffContextBg:theme.diff.background.context,diffLineNumber:theme.diff.lineNumber.text,diffAddedLineNumberBg:theme.diff.lineNumber.background.added,diffRemovedLineNumberBg:theme.diff.lineNumber.background.removed,markdownText:theme.markdown.text,markdownHeading:theme.markdown.heading,markdownLink:theme.markdown.link,markdownLinkText:theme.markdown.linkText,markdownCode:theme.markdown.code,markdownBlockQuote:theme.markdown.blockQuote,markdownEmph:theme.markdown.emphasis,markdownStrong:theme.markdown.strong,markdownHorizontalRule:theme.markdown.horizontalRule,markdownListItem:theme.markdown.listItem,markdownListEnumeration:theme.markdown.listEnumeration,markdownImage:theme.markdown.image,markdownImageText:theme.markdown.imageText,markdownCodeBlock:theme.markdown.codeBlock,syntaxComment:theme.syntax.comment,syntaxKeyword:theme.syntax.keyword,syntaxFunction:theme.syntax.function,syntaxVariable:theme.syntax.variable,syntaxString:theme.syntax.string,syntaxNumber:theme.syntax.number,syntaxType:theme.syntax.type,syntaxOperator:theme.syntax.operator,syntaxPunctuation:theme.syntax.punctuation,thinkingOpacity:0.6
7423
7312
  }}
7313
+ function bindToolbarActionState(context,api){setQuickActionStateSource(api,(id)=>{const route=context.ui.router.current()
7314
+ if(id!=="session.compact"||route.type!=="session")
7315
+ return
7316
+ const revert=context.data.session.get(route.sessionID)?.revert?.messageID
7317
+ return context.data.session.message.list(route.sessionID).some((message)=>(!revert||message.id<revert)&&message.type==="compaction"&&message.status==="running")?"compacting":"idle"
7318
+ })
7319
+ }
7424
7320
 
7425
7321
 
7426
7322
  function createV2UI(context){let dialogOpen=false
7427
7323
  function DialogPrompt(props){let active=true
7428
- onCleanup26(()=>{active=false
7324
+ onCleanup28(()=>{active=false
7429
7325
  })
7430
- onMount7(async ()=>{const value=await context.ui.dialog.prompt({title:props.title,placeholder:props.placeholder,value:props.value
7326
+ onMount6(async ()=>{const value=await context.ui.dialog.prompt({title:props.title,placeholder:props.placeholder,value:props.value
7431
7327
  })
7432
7328
  if(!active)
7433
7329
  return
@@ -7439,9 +7335,9 @@ props.onConfirm?.(value)
7439
7335
  return _$createElement("box")
7440
7336
  }
7441
7337
  function DialogConfirm(props){let active=true
7442
- onCleanup26(()=>{active=false
7338
+ onCleanup28(()=>{active=false
7443
7339
  })
7444
- onMount7(async ()=>{const confirmed=await context.ui.dialog.confirm({title:props.title,message:props.message
7340
+ onMount6(async ()=>{const confirmed=await context.ui.dialog.confirm({title:props.title,message:props.message
7445
7341
  })
7446
7342
  if(!active)
7447
7343
  return
@@ -7506,17 +7402,80 @@ context.ui.router.navigate({type:"plugin",name,data:params})
7506
7402
  }
7507
7403
  setHostCapabilities(api,{todo:true,lsp:false,titleVisibility:false,permissionMode:false
7508
7404
  })
7405
+ bindToolbarActionState(context,api)
7509
7406
  return{api,async dispose(){controller.abort()
7510
7407
  for(let index=disposers.length-1;index>=0; index--)
7511
7408
  await disposers[index]()
7512
7409
  disposers.length=0
7513
7410
  }}}
7411
+ var statuses=new Set(["pending","in_progress","completed","cancelled"])
7412
+ function parseTodos(value){if(!Array.isArray(value))
7413
+ return []
7414
+ return value.flatMap((item)=>{if(!item||typeof item!=="object"||!("content" in item)||typeof item.content!=="string"||!item.content)
7415
+ return []
7416
+ const status="status" in item&&typeof item.status==="string"&&statuses.has(item.status)?item.status:"pending"
7417
+ return [{content:item.content,status}]
7418
+ })
7419
+ }
7420
+ function nativeTodos(messages,boundary){const boundaryIndex=boundary?messages.findIndex((message)=>message.id===boundary):-1
7421
+ const end=boundaryIndex===-1?messages.length:boundaryIndex
7422
+ for(let index=end-1;index>=0; index--){const message=messages[index]
7423
+ if(message.type!=="assistant")
7424
+ continue
7425
+ for(let part=message.content.length-1;part>=0; part--){const item=message.content[part]
7426
+ if(item.type==="tool"&&item.name==="todowrite"&&item.state.status==="completed")
7427
+ return parseTodos(item.state.input.todos)
7428
+ }}
7429
+ return []
7430
+ }
7431
+ function createNativeTodoController(context,api){const requests=createRequestState(api.lifecycle.signal)
7432
+ const pending=new Map
7433
+ let activeTarget
7434
+ function target(sessionID){const session=api.state.session.get(sessionID)
7435
+ const directory=session?.directory??api.state.path.directory
7436
+ const workspace=session?.workspaceID
7437
+ return{key:JSON.stringify([sessionID,directory,workspace??null]),sessionID,routing:{directory,...workspace&&{workspace}}}}
7438
+ function list(sessionID){return nativeTodos(context.data.session.message.list(sessionID),context.data.session.get(sessionID)?.revert?.messageID)
7439
+ }
7440
+ function refresh(sessionID,force=false){if(api.lifecycle.signal.aborted)
7441
+ return Promise.resolve([])
7442
+ const current=target(sessionID)
7443
+ const existing=pending.get(current.key)
7444
+ if(existing&&!force)
7445
+ return existing
7446
+ const requestState=requests.start(current.key,"refresh native todos",context.data.session.message.list(sessionID).length>0,force)
7447
+ if(!requestState)
7448
+ return existing
7449
+ const request=Promise.try(()=>Promise.all([context.data.session.sync(sessionID),context.data.session.message.sync(sessionID)])).then(()=>{if(!requestState.isCurrent())
7450
+ return []
7451
+ requestState.succeed()
7452
+ return list(sessionID)
7453
+ }).catch((error)=>{requestState.fail(error)
7454
+ throw error
7455
+ }).finally(()=>{requestState.finish()
7456
+ if(pending.get(current.key)===request)
7457
+ pending.delete(current.key)
7458
+ })
7459
+ pending.set(current.key,request)
7460
+ return request
7461
+ }
7462
+ return{source:"native",target,list,refresh,state:(sessionID)=>requests.state(target(sessionID).key),retry:(sessionID)=>refresh(sessionID,true),activate(sessionID){const key=target(sessionID).key
7463
+ if(activeTarget!==key){requests.abortAll()
7464
+ pending.clear()
7465
+ activeTarget=key
7466
+ }
7467
+ return()=>{if(activeTarget!==key)
7468
+ return
7469
+ activeTarget=undefined
7470
+ requests.abortAll()
7471
+ pending.clear()
7472
+ }}}}
7514
7473
  function loadNavigatorUpdates(){const path=import.meta.url.includes("/dist/tui.js")?"./navigator-updates.js":"../navigator-updates"
7515
7474
  return import(path)
7516
7475
  }
7517
- async function setupNavigator(api,options,readProject,managedTodo,hostContext){const config=pluginConfig(undefined)
7476
+ async function setupNavigator(api,options,readProject,todoController,hostContext){const config=pluginConfig(undefined)
7518
7477
  const configured=await loadConfiguredDefaults(api,options,readProject)
7519
- const todo=managedTodo??createTodoController(api)
7478
+ const todo=todoController??createTodoController(api)
7520
7479
  const subagents=createSubagentController(api)
7521
7480
  const skills=createSkillController(api)
7522
7481
  const preferences=createPreferencesController(api,config,createPreferencesStore(api.state.path.state),configured)
@@ -7524,9 +7483,9 @@ const limitsPath=import.meta.url.includes("/dist/tui.js")?"./provider-limits.js"
7524
7483
  const limitsModule=await import(limitsPath)
7525
7484
  const LimitsSection=limitsModule.ProviderLimitsSection
7526
7485
  const{controller:limits,codex,accountSource,selectModel,modelSelection
7527
- }=limitsModule.createProviderQuotaIntegration(api,preferences,"0.21.8",hostContext)
7486
+ }=limitsModule.createProviderQuotaIntegration(api,preferences,"0.22.0",hostContext)
7528
7487
  const mcp=createMcpController(api,preferences.persistMcp,preferences)
7529
- const interaction=createSidebarInteraction(api,()=>openKeyboardHelp(api,preferences.lspIconStyle,preferences.cornerFont))
7488
+ const interaction=createSidebarInteraction(api,()=>openKeyboardHelp(api,preferences.lspIconStyle,preferences.cornerFont,sidebarShortcutActions(api)))
7530
7489
  const startup=createStartupSessionController(api,preferences)
7531
7490
  api.lifecycle.onDispose(()=>preferences.flush())
7532
7491
  api.lifecycle.onDispose(()=>limits.dispose())
@@ -7552,7 +7511,7 @@ api.slots.register({order:100,slots:{app(){return _$createComponent(IconProvider
7552
7511
  },interaction,skills,subagents,mcp
7553
7512
  }),_$createComponent(FirstRunWizardPersistence,{api,preferences
7554
7513
  }),_$createComponent(StartupSessionBinding,{api,controller:startup
7555
- }),_$createComponent(UpgradeNotesBinding,{api,preferences,version:"0.21.8"
7514
+ }),_$createComponent(UpgradeNotesBinding,{api,preferences,version:"0.22.0"
7556
7515
  }),_$createComponent(McpPersistence,{api,controller:mcp
7557
7516
  })]
7558
7517
  }})
@@ -7585,19 +7544,19 @@ return result.data?.type==="text"?result.data.content:undefined
7585
7544
  })
7586
7545
  const{createVersionStatus,createVersionUpdateActions,createOpenCodeV1VersionUpdater
7587
7546
  }=await loadNavigatorUpdates()
7588
- const versionStatus=createVersionStatus(api,"0.21.8")
7589
- const versionUpdates=createVersionUpdateActions(api,versionStatus,createOpenCodeV1VersionUpdater(api,meta),()=>preferences.rememberNavigatorVersionBeforeUpdate("0.21.8"))
7547
+ const versionStatus=createVersionStatus(api,"0.22.0")
7548
+ const versionUpdates=createVersionUpdateActions(api,versionStatus,createOpenCodeV1VersionUpdater(api,meta),()=>preferences.rememberNavigatorVersionBeforeUpdate("0.22.0"))
7590
7549
  api.slots.register({order:90,slots:{sidebar_footer(_context,props){return _$createComponent(IconProvider,{get style(){return preferences.lspIconStyle
7591
7550
  },get multilineCorners(){return preferences.cornerFont
7592
7551
  },get children(){return _$createComponent(VersionFooter,{api,get sessionID(){return props.session_id
7593
- },navigatorVersion:"0.21.8",status:versionStatus,get onOpenCodeUpdate(){return versionUpdates.openCode
7552
+ },navigatorVersion:"0.22.0",status:versionStatus,get onOpenCodeUpdate(){return versionUpdates.openCode
7594
7553
  },get onNavigatorUpdate(){return versionUpdates.navigator
7595
7554
  }})
7596
7555
  }})
7597
7556
  }}})
7598
7557
  }
7599
7558
  var setupOpenCodeV2=async (context)=>{const adapter=createOpenCodeV2Api(context)
7600
- const todo=createNavigatorTodoController(context,adapter.api)
7559
+ const todo=createNativeTodoController(context,adapter.api)
7601
7560
  const{mcp,skills,preferences
7602
7561
  }=await setupNavigator(adapter.api,context.options,async ()=>{if(!context.client.file?.read)
7603
7562
  return
@@ -7606,15 +7565,15 @@ return new TextDecoder().decode(await context.client.file.read({location:context
7606
7565
  },todo,context)
7607
7566
  const{createVersionStatus,createVersionUpdateActions,createOpenCodeV2VersionUpdater
7608
7567
  }=await loadNavigatorUpdates()
7609
- const versionStatus=createVersionStatus(adapter.api,"0.21.8")
7610
- const versionUpdates=createVersionUpdateActions(adapter.api,versionStatus,createOpenCodeV2VersionUpdater(context),()=>preferences.rememberNavigatorVersionBeforeUpdate("0.21.8"))
7568
+ const versionStatus=createVersionStatus(adapter.api,"0.22.0")
7569
+ const versionUpdates=createVersionUpdateActions(adapter.api,versionStatus,createOpenCodeV2VersionUpdater(context),()=>preferences.rememberNavigatorVersionBeforeUpdate("0.22.0"))
7611
7570
  const disposeFooter=context.ui.slot({append:"sidebar.footer",render:()=>_$createComponent(IconProvider,{get style(){return preferences.lspIconStyle
7612
7571
  },get multilineCorners(){return preferences.cornerFont
7613
7572
  },get children(){var _el$=_$createElement("box")
7614
7573
  _$setProp(_el$,"flexDirection","row")
7615
7574
  _$setProp(_el$,"justifyContent","space-between")
7616
7575
  _$insert(_el$,_$createComponent(VersionSummary,{get api(){return adapter.api
7617
- },navigatorVersion:"0.21.8",status:versionStatus,get onOpenCodeUpdate(){return versionUpdates.openCode
7576
+ },navigatorVersion:"0.22.0",status:versionStatus,get onOpenCodeUpdate(){return versionUpdates.openCode
7618
7577
  },get onNavigatorUpdate(){return versionUpdates.navigator
7619
7578
  }}),null)
7620
7579
  _$insert(_el$,_$createComponent(SettingsFooterButton,{get api(){return adapter.api
@@ -7629,5 +7588,5 @@ await adapter.dispose()
7629
7588
  var plugin={id:PLUGIN_ID,tui:setupOpenCodeV1,setup:setupOpenCodeV2
7630
7589
  }
7631
7590
  var plugin_default=plugin
7632
- export{DEFAULT_SECTION_EXPANSION,DialogAction,DialogHeader,DialogSurface,FOCUS_COMMAND,FirstRunWizard,GuardedConfirmation,KeyboardHelpDialog,LspBadge,McpSection,SelectionMenu as PresetMenu,QUICK_ACTIONS,Section,SectionFilter,SelectionBox,SelectionMenu,SettingsDialog,SidebarFocusBinding,SidebarToggleBinding,SkillsSection,createDialogStack,createMcpController,createPreferencesController,createSidebarInteraction,createSkillController,createSubagentController,createTodoController,plugin_default as default,isEffectivelyVisible,lspIcon,matchesFilter,openFirstRunWizard,openKeyboardHelp,openSettings,showFirstRunWizard,subtleLineColor,useDialogScroll,useDialogState,useDialogs,useIcons
7591
+ export{DEFAULT_SECTION_EXPANSION,DialogAction,DialogHeader,DialogSurface,FOCUS_COMMAND,FirstRunWizard,GuardedConfirmation,IconControl,IconPicker,KeyboardHelpDialog,LspBadge,McpSection,SelectionMenu as PresetMenu,QUICK_ACTIONS,QUICK_ACTION_IDS,Section,SectionFilter,SelectionBox,SelectionMenu,SettingsDialog,SidebarFocusBinding,SidebarToggleBinding,SkillsSection,Tab,TodoSection,createDialogStack,createMcpController,createNativeTodoController,createPreferencesController,createQuickActionRevision,createSidebarInteraction,createSkillController,createSubagentController,createTodoController,currentPermissionMode,plugin_default as default,hostCapabilities,hostCapabilityUnavailable,isEffectivelyVisible,lspIcon,matchesFilter,openFirstRunWizard,openKeyboardHelp,openSettings,orderQuickActionIds,parseQuickActionOrder,parseQuickActionVisibility,quickActionDisabledReason,quickActionLabel,quickActionRequiresSession,quickActionState,quickActionStates,setHostCapabilities,setQuickActionStateSource,showFirstRunWizard,subtleLineColor,supportsPermissionMode,supportsSidebarSection,supportsTitleVisibility,terminalIcon,terminalIconIDs,terminalIconLabel,useDialogScroll,useDialogState,useDialogs,useIcons
7633
7592
  }