opencode-navigator 0.19.3 → 0.21.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/CHANGELOG.md +16 -0
- package/PROVIDERS.md +92 -0
- package/README.md +136 -10
- package/dist/{chunk-r37n7w97.js → chunk-c1kw6ktv.js} +3 -4
- package/dist/chunk-cmmnfes2.js +7 -0
- package/dist/layout-preset-actions.js +438 -0
- package/dist/mcp-groups.js +4 -4
- package/dist/project-profile.js +280 -0
- package/dist/provider-limits.js +1027 -0
- package/dist/quick-actions-settings.js +2 -5
- package/dist/rpc.js +6 -1
- package/dist/server.js +589 -1
- package/dist/settings-import.js +40 -0
- package/dist/skill-groups.js +4 -4
- package/dist/trusted-skills.js +22 -0
- package/dist/tui.js +299 -273
- package/package.json +16 -11
- package/scripts/save-project-profile.mjs +41 -0
- package/scripts/update-local-snapshot.mjs +14 -12
|
@@ -0,0 +1,438 @@
|
|
|
1
|
+
import {SECTION_DEFINITIONS,PLUGIN_ID
|
|
2
|
+
} from "./chunk-cmmnfes2.js";
|
|
3
|
+
import {createComponent as _$createComponent7} from "@opentui/solid"
|
|
4
|
+
import {setProp as _$setProp5} from "@opentui/solid"
|
|
5
|
+
import {effect as _$effect5} from "@opentui/solid"
|
|
6
|
+
import {createTextNode as _$createTextNode5} from "@opentui/solid"
|
|
7
|
+
import {insertNode as _$insertNode5} from "@opentui/solid"
|
|
8
|
+
import {createElement as _$createElement5} from "@opentui/solid"
|
|
9
|
+
import {SelectionMenu} from "./tui.js"
|
|
10
|
+
import {mergeProps as _$mergeProps2} from "@opentui/solid"
|
|
11
|
+
import {createComponent as _$createComponent6} from "@opentui/solid"
|
|
12
|
+
import {memo as _$memo4} from "@opentui/solid"
|
|
13
|
+
import {For as For3,createMemo as createMemo3,onMount as onMount2} from "solid-js"
|
|
14
|
+
import {useDialogs as useDialogs3,useIcons as useIcons6} from "./tui.js"
|
|
15
|
+
import {createMemo} from "solid-js"
|
|
16
|
+
function mcpToggleAction(status){if(status==="pending")
|
|
17
|
+
return
|
|
18
|
+
return status==="connected"?"disconnect":"connect"
|
|
19
|
+
}
|
|
20
|
+
function mcpPresetPreview(items,states){const byName=new Map(items.map((item)=>[item.name,item]))
|
|
21
|
+
const names=[...new Set([...Object.keys(states),...byName.keys()])].sort((a,b)=>a.localeCompare(b))
|
|
22
|
+
const rows=names.map((name)=>{const item=byName.get(name)
|
|
23
|
+
const desired=Object.hasOwn(states,name)?states[name]:undefined
|
|
24
|
+
const action=item&&mcpToggleAction(item.status)
|
|
25
|
+
let change="unchanged"
|
|
26
|
+
if(desired&&!item)
|
|
27
|
+
change="missing"
|
|
28
|
+
else if(desired&&!action)
|
|
29
|
+
change="unavailable"
|
|
30
|
+
else if(desired==="enabled"&&action==="connect"||desired==="disabled"&&action==="disconnect"){change=action
|
|
31
|
+
}
|
|
32
|
+
return{name,status:item?.status,desired,change}})
|
|
33
|
+
const changes=rows.flatMap((row)=>row.change==="connect"||row.change==="disconnect"?[{name:row.name,action:row.change}]:[])
|
|
34
|
+
return{rows,changes}}
|
|
35
|
+
function createLayoutPresetPreview(preferences,name){const scope=preferences.selectedScopeKey()
|
|
36
|
+
const valid=()=>preferences.selectedScopeKey()===scope
|
|
37
|
+
const preset=createMemo(()=>preferences.layoutPresets()[name])
|
|
38
|
+
const preview=createMemo(()=>{const value=preset()
|
|
39
|
+
return value?preferences.previewLayoutPreset(value):undefined
|
|
40
|
+
})
|
|
41
|
+
return{valid,preview,scope:preferences.preferenceScopeLabel,blocked:()=>preset()?"":"Preset no longer exists.",apply(){const value=preset()
|
|
42
|
+
if(!valid()||!value)
|
|
43
|
+
return false
|
|
44
|
+
preferences.applyLayoutPreset(value)
|
|
45
|
+
return true
|
|
46
|
+
}}}
|
|
47
|
+
function createMcpPresetPreview(controller,preferences,name){const target=controller.target()
|
|
48
|
+
const valid=()=>{const current=controller.target()
|
|
49
|
+
return current.key===target.key&¤t.scope===target.scope
|
|
50
|
+
}
|
|
51
|
+
const preset=createMemo(()=>preferences.mcpPresets()[name])
|
|
52
|
+
const preview=createMemo(()=>mcpPresetPreview(controller.list(target),preset()??{}))
|
|
53
|
+
const state=createMemo(()=>controller.state(target))
|
|
54
|
+
const blocked=createMemo(()=>{if(!preset())
|
|
55
|
+
return "Preset no longer exists."
|
|
56
|
+
if(controller.mutating(target))
|
|
57
|
+
return "Wait for the current MCP operation to finish."
|
|
58
|
+
if(state().error)
|
|
59
|
+
return `Could not refresh MCP: ${state().error.message}. Retry to update the preview.`
|
|
60
|
+
return state().status==="ready"?"":"Refreshing MCP states\u2026"
|
|
61
|
+
})
|
|
62
|
+
return{valid,preview,blocked,scope:target.scope,refresh(){if(valid()&&!controller.mutating(target))
|
|
63
|
+
controller.refresh(target,true).catch(()=>{})
|
|
64
|
+
},apply(){const value=preset()
|
|
65
|
+
return value&&valid()&&!blocked()?controller.applyPreset(name,value,target):undefined
|
|
66
|
+
}}}
|
|
67
|
+
import {mergeProps as _$mergeProps} from "@opentui/solid"
|
|
68
|
+
import {createComponent as _$createComponent5} from "@opentui/solid"
|
|
69
|
+
import {memo as _$memo3} from "@opentui/solid"
|
|
70
|
+
import {For as For2,createMemo as createMemo2,onMount} from "solid-js"
|
|
71
|
+
import {useDialogs as useDialogs2,useIcons as useIcons5} from "./tui.js"
|
|
72
|
+
import {memo as _$memo} from "@opentui/solid"
|
|
73
|
+
import {use as _$use} from "@opentui/solid"
|
|
74
|
+
import {effect as _$effect3} from "@opentui/solid"
|
|
75
|
+
import {createTextNode as _$createTextNode3} from "@opentui/solid"
|
|
76
|
+
import {insertNode as _$insertNode3} from "@opentui/solid"
|
|
77
|
+
import {insert as _$insert3} from "@opentui/solid"
|
|
78
|
+
import {setProp as _$setProp3} from "@opentui/solid"
|
|
79
|
+
import {createElement as _$createElement3} from "@opentui/solid"
|
|
80
|
+
import {createComponent as _$createComponent3} from "@opentui/solid"
|
|
81
|
+
import {useTerminalDimensions} from "@opentui/solid"
|
|
82
|
+
import {Show as Show2,createEffect,createSignal,onCleanup} from "solid-js"
|
|
83
|
+
import {DialogHeader,DialogSurface,useDialogScroll,useDialogs,useIcons as useIcons3} from "./tui.js"
|
|
84
|
+
import {createComponent as _$createComponent} from "@opentui/solid"
|
|
85
|
+
import {effect as _$effect} from "@opentui/solid"
|
|
86
|
+
import {createTextNode as _$createTextNode} from "@opentui/solid"
|
|
87
|
+
import {insertNode as _$insertNode} from "@opentui/solid"
|
|
88
|
+
import {insert as _$insert} from "@opentui/solid"
|
|
89
|
+
import {setProp as _$setProp} from "@opentui/solid"
|
|
90
|
+
import {createElement as _$createElement} from "@opentui/solid"
|
|
91
|
+
import {Show} from "solid-js"
|
|
92
|
+
import {DialogAction,useIcons} from "./tui.js"
|
|
93
|
+
function PresetPreviewActions(props){const icons=useIcons()
|
|
94
|
+
return(()=>{var _el$=_$createElement("box"),_el$2=_$createElement("box"),_el$6=_$createElement("box")
|
|
95
|
+
_$insertNode(_el$,_el$2)
|
|
96
|
+
_$insertNode(_el$,_el$6)
|
|
97
|
+
_$setProp(_el$,"flexDirection","row")
|
|
98
|
+
_$setProp(_el$,"justifyContent","space-between")
|
|
99
|
+
_$setProp(_el$2,"flexGrow",1)
|
|
100
|
+
_$insert(_el$2,_$createComponent(Show,{get when(){return props.onRefresh
|
|
101
|
+
},get children(){var _el$3=_$createElement("text"),_el$4=_$createTextNode(` Refresh (`),_el$5=_$createTextNode(`)`)
|
|
102
|
+
_$insertNode(_el$3,_el$4)
|
|
103
|
+
_$insertNode(_el$3,_el$5)
|
|
104
|
+
_$setProp(_el$3,"onMouseUp",(event)=>{event.stopPropagation()
|
|
105
|
+
props.onRefresh?.()
|
|
106
|
+
})
|
|
107
|
+
_$insert(_el$3,()=>icons.icon("retry"),_el$4)
|
|
108
|
+
_$insert(_el$3,()=>icons.key("ctrl+r"),_el$5)
|
|
109
|
+
_$effect((_$p)=>_$setProp(_el$3,"fg",props.api.theme.current.accent,_$p))
|
|
110
|
+
return _el$3
|
|
111
|
+
}}))
|
|
112
|
+
_$setProp(_el$6,"flexDirection","row")
|
|
113
|
+
_$setProp(_el$6,"gap",1)
|
|
114
|
+
_$insert(_el$6,_$createComponent(DialogAction,{get api(){return props.api
|
|
115
|
+
},get id(){return `${props.prefix}.cancel`
|
|
116
|
+
},label:"Cancel",icon:"close",get selected(){return props.active==="cancel"
|
|
117
|
+
},onSelect:()=>props.onSelect("cancel"),onActivate:()=>props.onActivate("cancel")
|
|
118
|
+
}),null)
|
|
119
|
+
_$insert(_el$6,_$createComponent(DialogAction,{get api(){return props.api
|
|
120
|
+
},get id(){return `${props.prefix}.apply`
|
|
121
|
+
},label:"Apply",icon:"done",get selected(){return props.active==="apply"
|
|
122
|
+
},get disabled(){return props.disabled
|
|
123
|
+
},onSelect:()=>props.onSelect("apply"),onActivate:()=>props.onActivate("apply")
|
|
124
|
+
}),null)
|
|
125
|
+
return _el$
|
|
126
|
+
})()
|
|
127
|
+
}
|
|
128
|
+
import {effect as _$effect2} from "@opentui/solid"
|
|
129
|
+
import {createTextNode as _$createTextNode2} from "@opentui/solid"
|
|
130
|
+
import {insertNode as _$insertNode2} from "@opentui/solid"
|
|
131
|
+
import {insert as _$insert2} from "@opentui/solid"
|
|
132
|
+
import {createComponent as _$createComponent2} from "@opentui/solid"
|
|
133
|
+
import {setProp as _$setProp2} from "@opentui/solid"
|
|
134
|
+
import {createElement as _$createElement2} from "@opentui/solid"
|
|
135
|
+
import {For} from "solid-js"
|
|
136
|
+
import {SelectionBox,useIcons as useIcons2} from "./tui.js"
|
|
137
|
+
function PresetPreviewSummary(props){const icons=useIcons2()
|
|
138
|
+
const theme=()=>props.api.theme.current
|
|
139
|
+
const color=(tone)=>tone==="accent"?theme().accent:tone==="warning"?theme().warning:theme().textMuted
|
|
140
|
+
return(()=>{var _el$=_$createElement2("box")
|
|
141
|
+
_$setProp2(_el$,"flexDirection","row")
|
|
142
|
+
_$setProp2(_el$,"flexWrap","wrap")
|
|
143
|
+
_$setProp2(_el$,"gap",1)
|
|
144
|
+
_$insert2(_el$,_$createComponent2(For,{get each(){return props.stats
|
|
145
|
+
},children:(stat)=>_$createComponent2(SelectionBox,{height:1,get backgroundColor(){return theme().backgroundElement
|
|
146
|
+
},paddingLeft:1,paddingRight:1,get children(){var _el$2=_$createElement2("text"),_el$3=_$createTextNode2(` `)
|
|
147
|
+
_$insertNode2(_el$2,_el$3)
|
|
148
|
+
_$setProp2(_el$2,"wrapMode","none")
|
|
149
|
+
_$setProp2(_el$2,"height",1)
|
|
150
|
+
_$insert2(_el$2,()=>icons.icon(stat.icon),_el$3)
|
|
151
|
+
_$insert2(_el$2,()=>stat.label,null)
|
|
152
|
+
_$effect2((_$p)=>_$setProp2(_el$2,"fg",color(stat.tone),_$p))
|
|
153
|
+
return _el$2
|
|
154
|
+
}})
|
|
155
|
+
}))
|
|
156
|
+
return _el$
|
|
157
|
+
})()
|
|
158
|
+
}
|
|
159
|
+
function PresetPreviewFrame(props){const icons=useIcons3()
|
|
160
|
+
const dialogs=useDialogs(props.api)
|
|
161
|
+
const theme=()=>props.api.theme.current
|
|
162
|
+
const dimensions=useTerminalDimensions()
|
|
163
|
+
const scroll=useDialogScroll()
|
|
164
|
+
const [active,setActive]=createSignal("apply")
|
|
165
|
+
let body
|
|
166
|
+
const prefix=`${PLUGIN_ID}.preset-preview`
|
|
167
|
+
function activate(action){if(!props.valid()){dialogs.close()
|
|
168
|
+
return
|
|
169
|
+
}
|
|
170
|
+
if(action==="cancel"){dialogs.back()
|
|
171
|
+
return
|
|
172
|
+
}
|
|
173
|
+
if(props.blocked)
|
|
174
|
+
return
|
|
175
|
+
try{props.onApply()
|
|
176
|
+
} catch(error){props.api.ui.toast({variant:"error",title:props.title,message:error instanceof Error?error.message:"Could not apply preset",duration:4000
|
|
177
|
+
})
|
|
178
|
+
}}
|
|
179
|
+
const unregister=props.api.keymap.registerLayer({mode:"modal",priority:1000,commands:[{name:`${prefix}.up`,run:()=>body?.scrollBy(-1)
|
|
180
|
+
},{name:`${prefix}.down`,run:()=>body?.scrollBy(1)
|
|
181
|
+
},{name:`${prefix}.move`,run:()=>{setActive((value)=>value==="apply"?"cancel":"apply")
|
|
182
|
+
}},{name:`${prefix}.submit`,run:()=>activate(active())
|
|
183
|
+
},{name:`${prefix}.refresh`,run:()=>props.onRefresh?.()
|
|
184
|
+
}],bindings:[{key:"up",cmd:`${prefix}.up`
|
|
185
|
+
},{key:"down",cmd:`${prefix}.down`
|
|
186
|
+
},{key:"tab",cmd:`${prefix}.move`
|
|
187
|
+
},{key:"left",cmd:`${prefix}.move`
|
|
188
|
+
},{key:"right",cmd:`${prefix}.move`
|
|
189
|
+
},{key:"return",cmd:`${prefix}.submit`
|
|
190
|
+
},{key:"ctrl+r",cmd:`${prefix}.refresh`
|
|
191
|
+
}]
|
|
192
|
+
})
|
|
193
|
+
onCleanup(unregister)
|
|
194
|
+
createEffect(()=>{if(!props.valid())
|
|
195
|
+
dialogs.close()
|
|
196
|
+
})
|
|
197
|
+
return _$createComponent3(DialogSurface,{get api(){return props.api
|
|
198
|
+
},lift:true,get children(){return [_$createComponent3(DialogHeader,{get api(){return props.api
|
|
199
|
+
},get title(){return props.title
|
|
200
|
+
},get onBack(){return dialogs.back
|
|
201
|
+
}}),(()=>{var _el$=_$createElement3("box"),_el$2=_$createElement3("text"),_el$3=_$createTextNode3(` Scope`),_el$4=_$createElement3("text")
|
|
202
|
+
_$insertNode3(_el$,_el$2)
|
|
203
|
+
_$insertNode3(_el$,_el$4)
|
|
204
|
+
_$setProp3(_el$,"flexDirection","row")
|
|
205
|
+
_$setProp3(_el$,"gap",1)
|
|
206
|
+
_$insertNode3(_el$2,_el$3)
|
|
207
|
+
_$setProp3(_el$2,"flexShrink",0)
|
|
208
|
+
_$insert3(_el$2,()=>icons.icon("scope"),_el$3)
|
|
209
|
+
_$setProp3(_el$4,"flexGrow",1)
|
|
210
|
+
_$setProp3(_el$4,"wrapMode","none")
|
|
211
|
+
_$setProp3(_el$4,"truncate",true)
|
|
212
|
+
_$setProp3(_el$4,"height",1)
|
|
213
|
+
_$insert3(_el$4,()=>props.scope)
|
|
214
|
+
_$effect3((_p$)=>{var _v$=theme().accent,_v$2=theme().textMuted
|
|
215
|
+
_v$!==_p$.e&&(_p$.e=_$setProp3(_el$2,"fg",_v$,_p$.e))
|
|
216
|
+
_v$2!==_p$.t&&(_p$.t=_$setProp3(_el$4,"fg",_v$2,_p$.t))
|
|
217
|
+
return _p$
|
|
218
|
+
},{e:undefined,t:undefined
|
|
219
|
+
})
|
|
220
|
+
return _el$
|
|
221
|
+
})(),_$createComponent3(PresetPreviewSummary,{get api(){return props.api
|
|
222
|
+
},get stats(){return props.stats
|
|
223
|
+
}}),(()=>{var _el$5=_$createElement3("scrollbox"),_el$6=_$createElement3("box")
|
|
224
|
+
_$insertNode3(_el$5,_el$6)
|
|
225
|
+
_$use((node)=>{body=node
|
|
226
|
+
scroll.ref(node)
|
|
227
|
+
},_el$5)
|
|
228
|
+
_$setProp3(_el$5,"scrollX",false)
|
|
229
|
+
_$setProp3(_el$5,"contentOptions",{minHeight:0
|
|
230
|
+
})
|
|
231
|
+
_$setProp3(_el$6,"gap",1)
|
|
232
|
+
_$insert3(_el$6,()=>props.children)
|
|
233
|
+
_$effect3((_p$)=>{var{restore:_v$3,save:_v$4}=scroll,_v$5=Math.min(Math.max(2,Math.floor(dimensions().height*0.75)-14),Math.max(1,props.rowCount*3-1))
|
|
234
|
+
_v$3!==_p$.e&&(_p$.e=_$setProp3(_el$5,"renderBefore",_v$3,_p$.e))
|
|
235
|
+
_v$4!==_p$.t&&(_p$.t=_$setProp3(_el$5,"renderAfter",_v$4,_p$.t))
|
|
236
|
+
_v$5!==_p$.a&&(_p$.a=_$setProp3(_el$5,"height",_v$5,_p$.a))
|
|
237
|
+
return _p$
|
|
238
|
+
},{e:undefined,t:undefined,a:undefined
|
|
239
|
+
})
|
|
240
|
+
return _el$5
|
|
241
|
+
})(),_$createComponent3(Show2,{get when(){return props.blocked||props.notice
|
|
242
|
+
},get children(){var _el$7=_$createElement3("box"),_el$8=_$createElement3("text"),_el$9=_$createElement3("text")
|
|
243
|
+
_$insertNode3(_el$7,_el$8)
|
|
244
|
+
_$insertNode3(_el$7,_el$9)
|
|
245
|
+
_$setProp3(_el$7,"flexDirection","row")
|
|
246
|
+
_$setProp3(_el$7,"gap",1)
|
|
247
|
+
_$setProp3(_el$8,"flexShrink",0)
|
|
248
|
+
_$insert3(_el$8,()=>icons.icon(props.blocked?"error":"info"))
|
|
249
|
+
_$setProp3(_el$9,"flexGrow",1)
|
|
250
|
+
_$setProp3(_el$9,"wrapMode","word")
|
|
251
|
+
_$setProp3(_el$9,"height",2)
|
|
252
|
+
_$insert3(_el$9,()=>props.blocked||props.notice)
|
|
253
|
+
_$effect3((_p$)=>{var _v$6=props.blocked?theme().warning:theme().accent,_v$7=props.blocked?theme().warning:theme().textMuted
|
|
254
|
+
_v$6!==_p$.e&&(_p$.e=_$setProp3(_el$8,"fg",_v$6,_p$.e))
|
|
255
|
+
_v$7!==_p$.t&&(_p$.t=_$setProp3(_el$9,"fg",_v$7,_p$.t))
|
|
256
|
+
return _p$
|
|
257
|
+
},{e:undefined,t:undefined
|
|
258
|
+
})
|
|
259
|
+
return _el$7
|
|
260
|
+
}}),_$createComponent3(PresetPreviewActions,{get api(){return props.api
|
|
261
|
+
},prefix,get active(){return active()
|
|
262
|
+
},get disabled(){return Boolean(props.blocked)
|
|
263
|
+
},onSelect:setActive,onActivate:activate,get onRefresh(){return props.onRefresh
|
|
264
|
+
}}),(()=>{var _el$0=_$createElement3("text"),_el$1=_$createTextNode3(` scroll \xB7 `),_el$10=_$createTextNode3(` select \xB7 `),_el$11=_$createTextNode3(` confirm`)
|
|
265
|
+
_$insertNode3(_el$0,_el$1)
|
|
266
|
+
_$insertNode3(_el$0,_el$10)
|
|
267
|
+
_$insertNode3(_el$0,_el$11)
|
|
268
|
+
_$insert3(_el$0,()=>icons.key("up/down"),_el$1)
|
|
269
|
+
_$insert3(_el$0,()=>icons.key("tab"),_el$10)
|
|
270
|
+
_$insert3(_el$0,()=>icons.key("enter"),_el$11)
|
|
271
|
+
_$effect3((_$p)=>_$setProp3(_el$0,"fg",theme().textMuted,_$p))
|
|
272
|
+
return _el$0
|
|
273
|
+
})()]
|
|
274
|
+
}})
|
|
275
|
+
}
|
|
276
|
+
import {createComponent as _$createComponent4} from "@opentui/solid"
|
|
277
|
+
import {effect as _$effect4} from "@opentui/solid"
|
|
278
|
+
import {createTextNode as _$createTextNode4} from "@opentui/solid"
|
|
279
|
+
import {insertNode as _$insertNode4} from "@opentui/solid"
|
|
280
|
+
import {insert as _$insert4} from "@opentui/solid"
|
|
281
|
+
import {setProp as _$setProp4} from "@opentui/solid"
|
|
282
|
+
import {createElement as _$createElement4} from "@opentui/solid"
|
|
283
|
+
import {memo as _$memo2} from "@opentui/solid"
|
|
284
|
+
import {TextAttributes} from "@opentui/core"
|
|
285
|
+
import {SelectionBox as SelectionBox2,useIcons as useIcons4} from "./tui.js"
|
|
286
|
+
function PresetPreviewRow(props){const icons=useIcons4()
|
|
287
|
+
const theme=()=>props.api.theme.current
|
|
288
|
+
const emphasized=()=>props.status!=="unchanged"
|
|
289
|
+
const statusColor=()=>props.status==="changed"?theme().accent:props.status==="skipped"?theme().warning:theme().textMuted
|
|
290
|
+
return _$createComponent4(SelectionBox2,{get backgroundColor(){return _$memo2(()=>!!emphasized())()?theme().backgroundElement:theme().backgroundPanel
|
|
291
|
+
},paddingLeft:1,paddingRight:1,get children(){return [(()=>{var _el$=_$createElement4("box"),_el$2=_$createElement4("text"),_el$3=_$createElement4("text"),_el$4=_$createElement4("text"),_el$5=_$createTextNode4(` `)
|
|
292
|
+
_$insertNode4(_el$,_el$2)
|
|
293
|
+
_$insertNode4(_el$,_el$3)
|
|
294
|
+
_$insertNode4(_el$,_el$4)
|
|
295
|
+
_$setProp4(_el$,"flexDirection","row")
|
|
296
|
+
_$setProp4(_el$,"gap",1)
|
|
297
|
+
_$setProp4(_el$2,"flexShrink",0)
|
|
298
|
+
_$insert4(_el$2,()=>props.icon)
|
|
299
|
+
_$setProp4(_el$3,"flexGrow",1)
|
|
300
|
+
_$setProp4(_el$3,"wrapMode","none")
|
|
301
|
+
_$setProp4(_el$3,"truncate",true)
|
|
302
|
+
_$setProp4(_el$3,"height",1)
|
|
303
|
+
_$insert4(_el$3,()=>props.title)
|
|
304
|
+
_$insertNode4(_el$4,_el$5)
|
|
305
|
+
_$setProp4(_el$4,"flexShrink",0)
|
|
306
|
+
_$insert4(_el$4,()=>icons.icon(props.statusIcon),_el$5)
|
|
307
|
+
_$insert4(_el$4,()=>props.statusLabel,null)
|
|
308
|
+
_$effect4((_p$)=>{var _v$=statusColor(),_v$2=emphasized()?theme().text:theme().textMuted,_v$3=emphasized()?TextAttributes.BOLD:undefined,_v$4=statusColor(),_v$5=emphasized()?TextAttributes.BOLD:undefined
|
|
309
|
+
_v$!==_p$.e&&(_p$.e=_$setProp4(_el$2,"fg",_v$,_p$.e))
|
|
310
|
+
_v$2!==_p$.t&&(_p$.t=_$setProp4(_el$3,"fg",_v$2,_p$.t))
|
|
311
|
+
_v$3!==_p$.a&&(_p$.a=_$setProp4(_el$3,"attributes",_v$3,_p$.a))
|
|
312
|
+
_v$4!==_p$.o&&(_p$.o=_$setProp4(_el$4,"fg",_v$4,_p$.o))
|
|
313
|
+
_v$5!==_p$.i&&(_p$.i=_$setProp4(_el$4,"attributes",_v$5,_p$.i))
|
|
314
|
+
return _p$
|
|
315
|
+
},{e:undefined,t:undefined,a:undefined,o:undefined,i:undefined
|
|
316
|
+
})
|
|
317
|
+
return _el$
|
|
318
|
+
})(),(()=>{var _el$6=_$createElement4("text"),_el$7=_$createTextNode4(` `)
|
|
319
|
+
_$insertNode4(_el$6,_el$7)
|
|
320
|
+
_$setProp4(_el$6,"wrapMode","none")
|
|
321
|
+
_$setProp4(_el$6,"truncate",true)
|
|
322
|
+
_$setProp4(_el$6,"height",1)
|
|
323
|
+
_$insert4(_el$6,()=>icons.icon("right"),_el$7)
|
|
324
|
+
_$insert4(_el$6,()=>props.description,null)
|
|
325
|
+
_$effect4((_$p)=>_$setProp4(_el$6,"fg",theme().textMuted,_$p))
|
|
326
|
+
return _el$6
|
|
327
|
+
})()]
|
|
328
|
+
}})
|
|
329
|
+
}
|
|
330
|
+
function reportMcpApplyError(api,request){request.catch((error)=>api.ui.toast({variant:"error",title:"Preset apply",message:error instanceof Error?error.message:"MCP preset failed",duration:4000
|
|
331
|
+
}))
|
|
332
|
+
}
|
|
333
|
+
function mcpPreviewRows(model,icons){return model.preview().rows.map((row)=>{const unchanged=`${row.status ?? "not available"} \xB7 unchanged`
|
|
334
|
+
const description=row.desired?{missing:`Not available in this workspace \xB7 target ${row.desired} \xB7 skipped`,unavailable:`${row.status} \xB7 target ${row.desired} \xB7 skipped`,connect:`${row.status} -> enabled \xB7 connect`,disconnect:`${row.status} -> disabled \xB7 disconnect`,unchanged
|
|
335
|
+
}[row.change]:`${unchanged} (not in preset)`
|
|
336
|
+
return{icon:icons.icon("mcp"),title:row.name,description,changed:row.change==="connect"||row.change==="disconnect",skipped:row.change==="missing"||row.change==="unavailable",status:row.change==="connect"||row.change==="disconnect"?"changed":row.change==="missing"||row.change==="unavailable"?"skipped":"unchanged",statusIcon:row.change==="connect"?"connected":row.change==="disconnect"?"disconnected":row.change==="missing"||row.change==="unavailable"?"pending":"done",statusLabel:row.change==="connect"?"CONNECT":row.change==="disconnect"?"DISCONNECT":row.change==="missing"||row.change==="unavailable"?"SKIPPED":"UNCHANGED"
|
|
337
|
+
}}).sort((a,b)=>Number(b.changed)-Number(a.changed)||Number(b.skipped)-Number(a.skipped))
|
|
338
|
+
}
|
|
339
|
+
function LayoutPresetPreview(props){const dialogs=useDialogs3(props.api)
|
|
340
|
+
const icons=useIcons6()
|
|
341
|
+
const model=createLayoutPresetPreview(props.preferences,props.name)
|
|
342
|
+
const linked=props.preferences.workspaceProfiles?.()[props.name]
|
|
343
|
+
const mcpModel=props.controller&&linked?createMcpPresetPreview(props.controller,props.preferences,linked):undefined
|
|
344
|
+
const rows=createMemo3(()=>model.preview()?.rows.map((row)=>{const changes=[]
|
|
345
|
+
if(row.visibility[0]!==row.visibility[1])
|
|
346
|
+
changes.push(`${row.visibility[0] ? "visible" : "hidden"} -> ${row.visibility[1] ? "visible" : "hidden"}`)
|
|
347
|
+
if(row.expansion[0]!==row.expansion[1])
|
|
348
|
+
changes.push(`${row.expansion[0] ? "expanded" : "collapsed"} -> ${row.expansion[1] ? "expanded" : "collapsed"}`)
|
|
349
|
+
if(row.position[0]!==row.position[1])
|
|
350
|
+
changes.push(`position ${row.position[0]} -> ${row.position[1]}`)
|
|
351
|
+
return{icon:icons.section(row.section),title:`${row.position[1]}. ${SECTION_DEFINITIONS.find((section) => section.name === row.section).label}`,description:changes.join(" \xB7 ")||"No changes",changed:changes.length>0,status:changes.length>0?"changed":"unchanged",statusIcon:changes.length>0?"edit":"done",statusLabel:changes.length>0?"CHANGED":"UNCHANGED"
|
|
352
|
+
}}).sort((a,b)=>Number(b.changed)-Number(a.changed))??[])
|
|
353
|
+
const mcpRows=createMemo3(()=>mcpModel?mcpPreviewRows(mcpModel,icons):[])
|
|
354
|
+
const changed=()=>rows().filter((row)=>row.changed).length
|
|
355
|
+
onMount2(()=>mcpModel?.refresh())
|
|
356
|
+
return _$createComponent6(PresetPreviewFrame,{get api(){return props.api
|
|
357
|
+
},get title(){return `${mcpModel ? "Workspace profile" : "Layout preview"}: ${props.name}`
|
|
358
|
+
},get scope(){return mcpModel?`${model.scope()} \xB7 MCP ${mcpModel.scope}`:model.scope()
|
|
359
|
+
},get stats(){return [{icon:"edit",label:`${changed()} layout changed`,tone:"accent"
|
|
360
|
+
},{icon:"done",label:`${rows().length - changed()} layout unchanged`,tone:"muted"
|
|
361
|
+
}]
|
|
362
|
+
},get rowCount(){return rows().length + mcpRows().length
|
|
363
|
+
},valid:()=>model.valid()&&(!mcpModel||mcpModel.valid()),get blocked(){return model.blocked()||mcpModel?.blocked()
|
|
364
|
+
},get onRefresh(){return mcpModel?.refresh
|
|
365
|
+
},notice:mcpModel?"Applies both presets; layout stays session-only.":"Applies layout changes. Save current layout as default to persist them.",onApply:()=>{const request=mcpModel?.apply()
|
|
366
|
+
if(mcpModel&&!request)
|
|
367
|
+
return
|
|
368
|
+
if(!model.apply())
|
|
369
|
+
return
|
|
370
|
+
if(mcpModel)
|
|
371
|
+
dialogs.close()
|
|
372
|
+
else{dialogs.back()
|
|
373
|
+
dialogs.back()
|
|
374
|
+
}
|
|
375
|
+
props.api.ui.toast({variant:"success",title:mcpModel?"Workspace profile":"Layout presets",message:`${props.name} applied to ${model.scope()}`,duration:3000
|
|
376
|
+
})
|
|
377
|
+
if(request)
|
|
378
|
+
reportMcpApplyError(props.api,request)
|
|
379
|
+
},get children(){return [_$createComponent6(For3,{get each(){return rows()
|
|
380
|
+
},children:(row)=>_$createComponent6(PresetPreviewRow,_$mergeProps2({get api(){return props.api
|
|
381
|
+
}},row))
|
|
382
|
+
}),_$createComponent6(For3,{get each(){return mcpRows()
|
|
383
|
+
},children:(row)=>_$createComponent6(PresetPreviewRow,_$mergeProps2({get api(){return props.api
|
|
384
|
+
}},row))
|
|
385
|
+
})]
|
|
386
|
+
}})
|
|
387
|
+
}
|
|
388
|
+
function createLayoutPresetActions(input){function prompt(value="",renameFrom){input.dialogs.prompt({title:renameFrom?"Rename layout preset":"Save layout preset",description:()=>(()=>{var _el$=_$createElement5("text")
|
|
389
|
+
_$insertNode5(_el$,_$createTextNode5(`Save the current visible, expanded, and ordered sections.`))
|
|
390
|
+
_$effect5((_$p)=>_$setProp5(_el$,"fg",input.api.theme.current.textMuted,_$p))
|
|
391
|
+
return _el$
|
|
392
|
+
})(),placeholder:"Preset name",value,onConfirm(nameInput){const name=renameFrom?input.preferences.renameLayoutPreset(renameFrom,nameInput):input.preferences.saveLayoutPreset(nameInput)
|
|
393
|
+
input.dialogs.back()
|
|
394
|
+
if(renameFrom)
|
|
395
|
+
input.dialogs.back()
|
|
396
|
+
input.api.ui.toast({variant:"success",title:"Layout presets",message:renameFrom?`Renamed to ${name}`:`Saved ${name}`,duration:3000
|
|
397
|
+
})
|
|
398
|
+
}})
|
|
399
|
+
}
|
|
400
|
+
function open(name){const linked=input.preferences.workspaceProfiles?.()[name]
|
|
401
|
+
const link=()=>input.dialogs.prompt({title:`Link MCP \xB7 ${name}`,placeholder:"Preset; empty unlinks",value:linked??"",onConfirm(value){input.preferences.linkWorkspaceProfile?.(name,value.trim()||undefined)
|
|
402
|
+
input.dialogs.back()
|
|
403
|
+
input.dialogs.back()
|
|
404
|
+
}})
|
|
405
|
+
input.dialogs.open(()=>_$createComponent7(SelectionMenu,{get api(){return input.api
|
|
406
|
+
},title:name,get options(){return [{title:"Preview & apply",value:"apply",icon:"info",description:linked?`profile \xB7 ${linked}`:"review layout changes"
|
|
407
|
+
},{title:"Update from current",value:"update",icon:"save",description:"replace saved layout"
|
|
408
|
+
},{title:"Rename\u2026",value:"rename",description:"change preset name",icon:"edit"
|
|
409
|
+
},...input.mcp?[{title:linked?"Change MCP link\u2026":"Link MCP preset\u2026",value:"link",icon:"mcp",description:linked?`${linked} \xB7 empty unlinks`:"pair layout and MCP"
|
|
410
|
+
}]:[],{title:"Delete",value:"delete",description:"remove preset",icon:"delete"
|
|
411
|
+
}]
|
|
412
|
+
},onSelect:(option)=>{switch(option.value){case "apply":{input.dialogs.open(()=>_$createComponent7(LayoutPresetPreview,{get api(){return input.api
|
|
413
|
+
},get preferences(){return input.preferences
|
|
414
|
+
},get controller(){return input.mcp
|
|
415
|
+
},name
|
|
416
|
+
}),"large")
|
|
417
|
+
break
|
|
418
|
+
}
|
|
419
|
+
case "update":{input.preferences.updateLayoutPreset(name)
|
|
420
|
+
input.dialogs.back()
|
|
421
|
+
input.api.ui.toast({variant:"success",title:"Layout presets",message:`Updated ${name}`,duration:3000
|
|
422
|
+
})
|
|
423
|
+
break
|
|
424
|
+
}
|
|
425
|
+
case "rename":{prompt(name,name)
|
|
426
|
+
break
|
|
427
|
+
}
|
|
428
|
+
case "link":{link()
|
|
429
|
+
break
|
|
430
|
+
}
|
|
431
|
+
default:{input.preferences.deleteLayoutPreset(name)
|
|
432
|
+
input.dialogs.back()
|
|
433
|
+
}}}}))
|
|
434
|
+
}
|
|
435
|
+
return{open,prompt
|
|
436
|
+
}}
|
|
437
|
+
export{createLayoutPresetActions
|
|
438
|
+
}
|
package/dist/mcp-groups.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import {
|
|
2
|
-
} from "./chunk-
|
|
1
|
+
import {GroupAssignmentDialog
|
|
2
|
+
} from "./chunk-c1kw6ktv.js";
|
|
3
3
|
import {createComponent as _$createComponent2} from "@opentui/solid"
|
|
4
|
-
import {useDialogs} from "./tui.js"
|
|
4
|
+
import {SelectionMenu,useDialogs} from "./tui.js"
|
|
5
5
|
import {createComponent as _$createComponent} from "@opentui/solid"
|
|
6
6
|
function McpGroupAssignmentDialog(props){return _$createComponent(GroupAssignmentDialog,{get api(){return props.api
|
|
7
7
|
},get title(){return `Group for ${props.server}`
|
|
@@ -13,7 +13,7 @@ const options=()=>{const live=new Set(props.mcp.list(props.mcp.target()).map((it
|
|
|
13
13
|
return [...new Set([...live,...Object.keys(props.preferences.mcpServerGroups?.()??{})])].sort((a,b)=>a.localeCompare(b)).map((name)=>({title:name,value:name,description:[props.preferences.mcpServerGroups?.()[name]??"Ungrouped",!live.has(name)&&"not in workspace"].filter(Boolean).join(" \xB7 ")
|
|
14
14
|
}))
|
|
15
15
|
}
|
|
16
|
-
return _$createComponent2(
|
|
16
|
+
return _$createComponent2(SelectionMenu,{get api(){return props.api
|
|
17
17
|
},title:"MCP groups \xB7 user-wide",get options(){return options()
|
|
18
18
|
},onSelect:(option)=>dialogs.open(()=>_$createComponent2(McpGroupAssignmentDialog,{get api(){return props.api
|
|
19
19
|
},get preferences(){return props.preferences
|