opencode-navigator 0.26.0 → 0.27.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 +9 -0
- package/HOST_API.md +106 -6
- package/LINT_COVERAGE.md +5 -0
- package/PROVIDERS.md +9 -0
- package/README.md +86 -5
- package/dist/{chunk-bv0nm1tj.js → chunk-dm1y8x49.js} +2 -1
- package/dist/gui-experimental.cjs +15526 -0
- package/dist/layout-preset-actions.js +37 -14
- package/dist/native-todo-setup.js +2 -1
- package/dist/navigator-updates.js +2 -2
- package/dist/onboarding.js +11 -4
- package/dist/project-profile.js +34 -38
- package/dist/provider-limits.js +207 -149
- package/dist/quick-actions-settings.js +1 -1
- package/dist/runtime-dependencies.json +4 -4
- package/dist/server.js +379 -0
- package/dist/sidebar-settings.js +37 -34
- package/dist/sidebar-shortcuts.js +1 -1
- package/dist/toolbar-settings.js +68 -20
- package/dist/tui.js +711 -613
- package/dist/upgrade-notes.js +1 -1
- package/package.json +27 -12
- /package/dist/{chunk-pwa1wzer.js → chunk-rrvwmnyh.js} +0 -0
package/dist/tui.js
CHANGED
|
@@ -3,7 +3,6 @@ import {insert as _$insert,setProp as _$setProp,createElement as _$createElement
|
|
|
3
3
|
|
|
4
4
|
|
|
5
5
|
|
|
6
|
-
import {createSignal as createSignal2,createSignal,createEffect,onCleanup,createContext,useContext,createContext as createContext2,createSignal as createSignal3,onCleanup as onCleanup2,useContext as useContext2,createEffect as createEffect2,splitProps,untrack,splitProps as splitProps2,For,createEffect as createEffect3,onCleanup as onCleanup3,Show,createEffect as createEffect4,Show as Show2,splitProps as splitProps3,createEffect as createEffect5,createSignal as createSignal4,onCleanup as onCleanup4,onMount,Suspense,lazy,createSignal as createSignal5,createSignal as createSignal6,onCleanup as onCleanup5,Show as Show3,batch,createSignal as createSignal8,createSignal as createSignal7,createEffect as createEffect6,createSignal as createSignal9,onCleanup as onCleanup6,createSignal as createSignal10,createSignal as createSignal11,Suspense as Suspense2,lazy as lazy2,Index,onCleanup as onCleanup7,createSignal as createSignal12,onCleanup as onCleanup8,createEffect as createEffect8,onCleanup as onCleanup10,batch as batch2,createEffect as createEffect7,createMemo,createSignal as createSignal13,onCleanup as onCleanup9,onMount as onMount2,For as For2,For as For3,Show as Show4,createMemo as createMemo2,Suspense as Suspense3,lazy as lazy3,For as For6,createMemo as createMemo4,onMount as onMount4,For as For5,createMemo as createMemo3,onMount as onMount3,Show as Show6,createEffect as createEffect9,createSignal as createSignal14,onCleanup as onCleanup11,Show as Show5,For as For4,For as For7,createEffect as createEffect10,createMemo as createMemo5,onCleanup as onCleanup12,createEffect as createEffect11,createMemo as createMemo6,untrack as untrack2,Suspense as Suspense4,lazy as lazy4,onCleanup as onCleanup13,createEffect as createEffect12,onCleanup as onCleanup14,createSignal as createSignal15,createMemo as createMemo7,createSignal as createSignal16,createSignal as createSignal17,lazy as lazy5,Show as Show9,For as For8,Show as Show8,Show as Show7,createEffect as createEffect13,onCleanup as onCleanup15,onMount as onMount5,onCleanup as onCleanup16,onMount as onMount6,For as For9,createSignal as createSignal18,createSignal as createSignal19,onCleanup as onCleanup17,createSignal as createSignal20,Show as Show10,createSignal as createSignal22,createSignal as createSignal21,onCleanup as onCleanup18,For as For10,Show as Show13,createMemo as createMemo9,createComputed,createMemo as createMemo8,createSignal as createSignal23,untrack as untrack3,Show as Show11,createComputed as createComputed2,untrack as untrack4,Show as Show12,createSignal as createSignal25,createEffect as createEffect14,createSignal as createSignal24,on,createMemo as createMemo11,createSignal as createSignal28,createMemo as createMemo10,For as For11,Show as Show17,Show as Show14,Show as Show15,createSignal as createSignal26,createContext as createContext3,useContext as useContext3,Show as Show16,createSignal as createSignal27,onCleanup as onCleanup19,Show as Show23,createSignal as createSignal29,untrack as untrack5,createSignal as createSignal30,createSignal as createSignal31,createEffect as createEffect15,For as For13,Show as Show18,For as For12,createSignal as createSignal32,Show as Show19,Show as Show20,Show as Show21,Show as Show22,For as For14,Show as Show25,createMemo as createMemo13,Show as Show24,createMemo as createMemo12,createSignal as createSignal33,createContext as createContext4,useContext as useContext4,Show as Show26,Suspense as Suspense5,createEffect as createEffect16,onCleanup as onCleanup20,untrack as untrack6,For as For20,Match,Switch,createMemo as createMemo19,onCleanup as onCleanup26,For as For15,Show as Show28,createMemo as createMemo15,createSignal as createSignal35,createEffect as createEffect17,createMemo as createMemo14,onCleanup as onCleanup21,untrack as untrack7,Show as Show27,createEffect as createEffect18,createSignal as createSignal34,onCleanup as onCleanup22,For as For16,Show as Show30,createSignal as createSignal36,createEffect as createEffect19,createMemo as createMemo16,onCleanup as onCleanup23,untrack as untrack8,Show as Show29,For as For18,Show as Show33,createEffect as createEffect20,createMemo as createMemo17,createSignal as createSignal37,onCleanup as onCleanup24,untrack as untrack9,For as For17,Show as Show32,Show as Show31,Show as Show38,createEffect as createEffect21,createMemo as createMemo18,createSignal as createSignal38,onCleanup as onCleanup25,untrack as untrack10,Show as Show34,For as For19,Show as Show36,Show as Show35,Show as Show37,createEffect as createEffect22,createMemo as createMemo20,onCleanup as onCleanup27,untrack as untrack11,Show as Show39,createMemo as createMemo21,onCleanup as onCleanup28,createEffect as createEffect23,createMemo as createMemo22,on as on2,onCleanup as onCleanup29,createRoot,createSignal as createSignal39,getOwner,createSignal as createSignal40,onCleanup as onCleanup30,onMount as onMount7} from "solid-js"
|
|
7
6
|
var SIDEBAR_SECTIONS=["limits","todo","subagents","skills","quick_actions","lsp","mcp"]
|
|
8
7
|
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
8
|
function preferencesScope(path){return path.worktree||path.directory||"global"
|
|
@@ -85,6 +84,7 @@ const session=sessionID?api.state.session.get(sessionID):undefined
|
|
|
85
84
|
const directory=session?.directory??api.state.path.directory
|
|
86
85
|
const workspace=session?.workspaceID
|
|
87
86
|
return{key:JSON.stringify([directory,workspace??null]),routing:{directory,...workspace&&{workspace}}}}
|
|
87
|
+
import {createSignal as createSignal2,createSignal,createEffect,onCleanup,createContext,useContext,createContext as createContext2,createSignal as createSignal3,onCleanup as onCleanup2,useContext as useContext2,createEffect as createEffect2,splitProps,untrack,splitProps as splitProps2,For,createEffect as createEffect3,onCleanup as onCleanup3,Show,createEffect as createEffect4,Show as Show2,splitProps as splitProps3,createEffect as createEffect5,createSignal as createSignal4,onCleanup as onCleanup4,onMount,Suspense,lazy,batch,createSignal as createSignal5,createSignal as createSignal6,onCleanup as onCleanup5,Show as Show3,batch as batch2,createSignal as createSignal8,createSignal as createSignal7,createEffect as createEffect6,createSignal as createSignal9,onCleanup as onCleanup6,createSignal as createSignal10,createSignal as createSignal11,Suspense as Suspense2,lazy as lazy2,Index,onCleanup as onCleanup7,createEffect as createEffect8,onCleanup as onCleanup10,batch as batch3,createEffect as createEffect7,createMemo,createSignal as createSignal13,onCleanup as onCleanup9,onMount as onMount2,createSignal as createSignal12,onCleanup as onCleanup8,For as For2,For as For3,Show as Show4,createMemo as createMemo2,Suspense as Suspense3,lazy as lazy3,For as For6,createMemo as createMemo4,onMount as onMount4,For as For5,createMemo as createMemo3,onMount as onMount3,Show as Show6,createEffect as createEffect9,createSignal as createSignal14,onCleanup as onCleanup11,Show as Show5,For as For4,For as For7,createEffect as createEffect10,createMemo as createMemo5,onCleanup as onCleanup12,createEffect as createEffect11,createMemo as createMemo6,untrack as untrack2,Suspense as Suspense4,lazy as lazy4,onCleanup as onCleanup13,createEffect as createEffect12,onCleanup as onCleanup14,createSignal as createSignal15,createMemo as createMemo7,createSignal as createSignal16,createSignal as createSignal17,lazy as lazy5,Show as Show9,For as For8,Show as Show8,Show as Show7,createEffect as createEffect13,onCleanup as onCleanup15,onMount as onMount5,onCleanup as onCleanup16,onMount as onMount6,For as For9,createSignal as createSignal18,createSignal as createSignal19,onCleanup as onCleanup17,createSignal as createSignal20,Show as Show10,createSignal as createSignal22,createSignal as createSignal21,onCleanup as onCleanup18,For as For10,Show as Show13,createMemo as createMemo9,createComputed,createMemo as createMemo8,createSignal as createSignal23,untrack as untrack3,Show as Show11,createComputed as createComputed2,untrack as untrack4,Show as Show12,createSignal as createSignal25,createEffect as createEffect14,createSignal as createSignal24,on,createMemo as createMemo11,createSignal as createSignal28,createMemo as createMemo10,For as For11,Show as Show17,Show as Show14,Show as Show15,createSignal as createSignal26,createContext as createContext3,useContext as useContext3,Show as Show16,createSignal as createSignal27,onCleanup as onCleanup19,Show as Show23,createSignal as createSignal29,untrack as untrack5,createSignal as createSignal30,createSignal as createSignal31,createEffect as createEffect15,For as For13,Show as Show18,For as For12,createSignal as createSignal32,Show as Show19,Show as Show20,Show as Show21,Show as Show22,createSignal as createSignal33,createEffect as createEffect16,createMemo as createMemo12,on as on2,onCleanup as onCleanup20,For as For14,Show as Show25,createMemo as createMemo14,Show as Show24,createMemo as createMemo13,createSignal as createSignal34,createContext as createContext4,useContext as useContext4,Show as Show26,Suspense as Suspense5,createEffect as createEffect17,onCleanup as onCleanup21,untrack as untrack6,For as For20,Match,Switch,createMemo as createMemo20,onCleanup as onCleanup27,For as For15,Show as Show28,createMemo as createMemo16,createSignal as createSignal36,createEffect as createEffect18,createMemo as createMemo15,onCleanup as onCleanup22,untrack as untrack7,Show as Show27,createEffect as createEffect19,createSignal as createSignal35,onCleanup as onCleanup23,For as For16,Show as Show30,createSignal as createSignal37,createEffect as createEffect20,createMemo as createMemo17,onCleanup as onCleanup24,untrack as untrack8,Show as Show29,For as For18,Show as Show33,createEffect as createEffect21,createMemo as createMemo18,createSignal as createSignal38,onCleanup as onCleanup25,untrack as untrack9,For as For17,Show as Show32,Show as Show31,Show as Show38,createEffect as createEffect22,createMemo as createMemo19,createSignal as createSignal39,onCleanup as onCleanup26,untrack as untrack10,Show as Show34,For as For19,Show as Show36,Show as Show35,Show as Show37,createEffect as createEffect23,createMemo as createMemo21,onCleanup as onCleanup28,untrack as untrack11,Show as Show39,createMemo as createMemo22,onCleanup as onCleanup29,createRoot,createSignal as createSignal40,getOwner,createSignal as createSignal41,onCleanup as onCleanup30,onMount as onMount7} from "solid-js"
|
|
88
88
|
function mcpToggleAction(status){if(status==="pending")
|
|
89
89
|
return
|
|
90
90
|
return status==="connected"?"disconnect":"connect"
|
|
@@ -216,6 +216,8 @@ const rightRank=BUCKET_RANK[right.bucket]??1
|
|
|
216
216
|
return leftRank-rightRank||left.bucket.localeCompare(right.bucket)||left.name.localeCompare(right.name)
|
|
217
217
|
})
|
|
218
218
|
}
|
|
219
|
+
function serverKey(current,name){return JSON.stringify([current.key,name])
|
|
220
|
+
}
|
|
219
221
|
function bulkDescription(operation,action){if(operation.action==="preset")
|
|
220
222
|
return `apply ${operation.preset} MCP preset`
|
|
221
223
|
if(operation.group)
|
|
@@ -228,12 +230,8 @@ return Object.keys(presets).sort((left,right)=>left.localeCompare(right)).find((
|
|
|
228
230
|
return Object.keys(states).length===items.length&&items.every((item)=>item.status==="connected"&&states[item.name]==="enabled"||item.status==="disabled"&&states[item.name]==="disabled")
|
|
229
231
|
})
|
|
230
232
|
}
|
|
231
|
-
function
|
|
232
|
-
|
|
233
|
-
const error=status.error
|
|
234
|
-
return typeof error==="string"?error:undefined
|
|
235
|
-
}
|
|
236
|
-
function createMcpController(api,persist,preferences,source){const [snapshots,setSnapshots]=createSignal2({})
|
|
233
|
+
function createMcpModel(options,persist,preferences){const{source}=options
|
|
234
|
+
const [snapshots,setSnapshots]=createSignal2({})
|
|
237
235
|
const [mutationCounts,setMutationCounts]=createSignal2({})
|
|
238
236
|
const [bulkStates,setBulkStates]=createSignal2({})
|
|
239
237
|
const [selectedPresets,setSelectedPresets]=createSignal2({})
|
|
@@ -243,8 +241,8 @@ const mutationRetries=new Map
|
|
|
243
241
|
const bulkGenerations=new Map
|
|
244
242
|
const bulkRetries=new Map
|
|
245
243
|
const selectedPresetStates=new Map
|
|
246
|
-
const requests=createRequestState(
|
|
247
|
-
const serverRequests=createRequestState(
|
|
244
|
+
const requests=createRequestState(options.signal)
|
|
245
|
+
const serverRequests=createRequestState(options.signal)
|
|
248
246
|
let activation=0
|
|
249
247
|
let activeTarget
|
|
250
248
|
function changeMutationCount(current,offset){setMutationCounts((values)=>{const next=Math.max(0,(values[current.key]??0) + offset)
|
|
@@ -268,10 +266,7 @@ serverRequests.abortAll()
|
|
|
268
266
|
refreshing.clear()
|
|
269
267
|
activeTarget=current.key
|
|
270
268
|
}
|
|
271
|
-
function target(){
|
|
272
|
-
return{key:location.key,scope:preferencesScope({directory:location.routing.directory,worktree:api.state.path.worktree}),routing:location.routing
|
|
273
|
-
}}
|
|
274
|
-
function serverKey(current,name){return JSON.stringify([current.key,name])
|
|
269
|
+
function target(){return options.target()
|
|
275
270
|
}
|
|
276
271
|
function mutating(current=target()){return(mutationCounts()[current.key]??0)>0
|
|
277
272
|
}
|
|
@@ -306,7 +301,7 @@ const failed=state.failed.filter((candidate)=>candidate!==name)
|
|
|
306
301
|
bulkRetries.set(current.key,(bulkRetries.get(current.key)??[]).filter((candidate)=>candidate.name!==name))
|
|
307
302
|
return{...values,[current.key]:{...state,status:failed.length>0?"error":"ready",failed}}})
|
|
308
303
|
}
|
|
309
|
-
function list(current=target()){return source?source.list(current):snapshots()[current.key]??
|
|
304
|
+
function list(current=target()){return options.cache==="source"?source.list(current):snapshots()[current.key]??source.list(current)
|
|
310
305
|
}
|
|
311
306
|
async function refresh(current=target(),force=false){const pending=refreshing.get(current.key)
|
|
312
307
|
if(pending&&!force)
|
|
@@ -314,7 +309,7 @@ return pending
|
|
|
314
309
|
const requestState=requests.start(current.key,"refresh MCP servers",current.key in snapshots(),force)
|
|
315
310
|
if(!requestState)
|
|
316
311
|
return pending
|
|
317
|
-
const request=
|
|
312
|
+
const request=source.refresh(current,force,requestState.signal).then((items)=>{if(options.cache==="model"&&requestState.isCurrent())
|
|
318
313
|
setSnapshots((value)=>({...value,[current.key]:items}))
|
|
319
314
|
if(requestState.isCurrent())
|
|
320
315
|
reconcileSelectedPreset(current,items)
|
|
@@ -337,7 +332,7 @@ const requestState=serverRequests.start(key,operation,false)
|
|
|
337
332
|
if(!requestState)
|
|
338
333
|
return mutations.get(key)
|
|
339
334
|
changeMutationCount(current,1)
|
|
340
|
-
const request=
|
|
335
|
+
const request=options.change(current,name,action,requestState.signal).then(()=>{requestState.succeed()
|
|
341
336
|
mutationRetries.delete(key)
|
|
342
337
|
clearBulkFailure(current,name)
|
|
343
338
|
}).catch((error)=>{requestState.fail(error)
|
|
@@ -385,14 +380,14 @@ if(desired==="disabled"&&action==="disconnect"){await changeServer(current,item.
|
|
|
385
380
|
}
|
|
386
381
|
if(desired==="enabled"&&action==="connect"){await changeServer(current,item.name,"connect","restore MCP preference",false)
|
|
387
382
|
}}))
|
|
388
|
-
const failed=
|
|
389
|
-
if(failed.length>0){
|
|
383
|
+
const failed=options.signal?.aborted?[]:results.flatMap((result,index)=>result.status==="rejected"&&!isAbortError(result.reason)?[items[index].name]:[])
|
|
384
|
+
if(failed.length>0){options.notifications.show({variant:"warning",title:"MCP preferences",message:`Could not restore: ${failed.join(", ")}`
|
|
390
385
|
})
|
|
391
386
|
}
|
|
392
387
|
if(generation===activation&&target().key===current.key)
|
|
393
388
|
await refresh(current,true)
|
|
394
389
|
}
|
|
395
|
-
function reconnect(current=target()){return retryBackgroundRefresh(()=>activate(current),{signal:
|
|
390
|
+
function reconnect(current=target()){return retryBackgroundRefresh(()=>activate(current),{signal:options.signal})
|
|
396
391
|
}
|
|
397
392
|
function bulkState(current=target()){return bulkStates()[current.key]??{action:"connect",status:"idle",completed:0,total:0,failed:[]
|
|
398
393
|
}}
|
|
@@ -430,7 +425,7 @@ setBulkStates((values)=>({...values,[current.key]:{...operation,status:failed.le
|
|
|
430
425
|
if(failed.length>0&&activeTarget===current.key){let action=operation.action==="preset"?`apply ${operation.preset}`:operation.action
|
|
431
426
|
if(operation.group)
|
|
432
427
|
action += ` ${operation.group}`
|
|
433
|
-
|
|
428
|
+
options.notifications.show({variant:"warning",title:"MCP servers",message:`Could not ${action}: ${failed.join(", ")}`
|
|
434
429
|
})
|
|
435
430
|
}}
|
|
436
431
|
return{list,refresh,reconnect,activate,deactivate(current){if(activeTarget!==current.key)
|
|
@@ -497,6 +492,14 @@ return
|
|
|
497
492
|
const changes=bulkRetries.get(current.key)??[]
|
|
498
493
|
return changeMany({action:state.action,...state.preset&&{preset:state.preset},...state.group&&{group:state.group}},changes,current)
|
|
499
494
|
}}}
|
|
495
|
+
function createMcpController(api,persist,preferences,source){return createMcpModel({target(){const location=currentLocation(api)
|
|
496
|
+
return{...location,scope:preferencesScope({directory:location.routing.directory,worktree:api.state.path.worktree})
|
|
497
|
+
}},signal:api.lifecycle?.signal,notifications:{show:(input)=>api.ui.toast({...input,duration:4000})},cache:source?"source":"model",source:source??{list:()=>api.state.mcp(),async refresh(target,_force,signal){const result=await api.client.mcp.status(target.routing,{throwOnError:true,signal})
|
|
498
|
+
return Object.entries(result.data??{}).map(([name,status])=>({name,status:status.status,error:"error" in status?status.error:undefined
|
|
499
|
+
})).sort((left,right)=>left.name.localeCompare(right.name))
|
|
500
|
+
}},async change(target,name,action,signal){await api.client.mcp[action]({name,...target.routing},{throwOnError:true,signal})
|
|
501
|
+
}},persist,preferences)
|
|
502
|
+
}
|
|
500
503
|
|
|
501
504
|
|
|
502
505
|
|
|
@@ -1195,12 +1198,16 @@ _$insert(_el$,_$createComponent(Suspense,{get children(){return _$createComponen
|
|
|
1195
1198
|
return _el$
|
|
1196
1199
|
})()
|
|
1197
1200
|
}
|
|
1201
|
+
var ICON_CHOICE_IDS=["plus","check","circle","star","pin","bolt","book","search","code","terminal","gear","shield","lock","unlock","eye","clock","refresh","history","copy","export","edit","fork","list","play","pause","stop","rocket","bug","beaker","wand","cloud","server","folder","file","heart","lightbulb","arrow-up","arrow-down","warning","close"]
|
|
1202
|
+
var choices=new Set(ICON_CHOICE_IDS)
|
|
1203
|
+
function iconChoiceLabel(id){return id.replaceAll("-"," ")
|
|
1204
|
+
}
|
|
1198
1205
|
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"]
|
|
1199
1206
|
}
|
|
1200
|
-
var terminalIconIDs=
|
|
1207
|
+
var terminalIconIDs=[...ICON_CHOICE_IDS]
|
|
1201
1208
|
function terminalIcon(id,style){return(glyphs[id]??glyphs.bolt)[style==="nerd"?0:1]
|
|
1202
1209
|
}
|
|
1203
|
-
function terminalIconLabel(id){return id
|
|
1210
|
+
function terminalIconLabel(id){return iconChoiceLabel(id)
|
|
1204
1211
|
}
|
|
1205
1212
|
function McpErrorDialog(props){return _$createComponent(SelectionMenu,{get api(){return props.api
|
|
1206
1213
|
},get title(){return `MCP error \xB7 ${props.name}`
|
|
@@ -1209,6 +1216,9 @@ function McpErrorDialog(props){return _$createComponent(SelectionMenu,{get api()
|
|
|
1209
1216
|
},onSelect:()=>{}})
|
|
1210
1217
|
}
|
|
1211
1218
|
|
|
1219
|
+
function builtInPreferences(defaults){return{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
|
|
1220
|
+
},layout:{sections:defaults.sections,expanded:DEFAULT_SECTION_EXPANSION,order:defaults.sectionOrder??[...SIDEBAR_SECTIONS]
|
|
1221
|
+
},desiredMcpStates:{}}}
|
|
1212
1222
|
function codexBindingKey(target){return JSON.stringify([target.providerID,target.connectionID?{connectionID:target.connectionID}:null])
|
|
1213
1223
|
}
|
|
1214
1224
|
function legacyKey(key){try{const value=JSON.parse(key)
|
|
@@ -1333,6 +1343,83 @@ function serializePortableSettings(layout,mcp,behavior){return `${JSON.stringify
|
|
|
1333
1343
|
}, undefined, 2)}
|
|
1334
1344
|
`
|
|
1335
1345
|
}
|
|
1346
|
+
function normalizePresetName(value){const name=value.trim()
|
|
1347
|
+
if(!name)
|
|
1348
|
+
throw new Error("Enter a preset name")
|
|
1349
|
+
if(name.length>64)
|
|
1350
|
+
throw new Error("Preset names can contain at most 64 characters")
|
|
1351
|
+
return name
|
|
1352
|
+
}
|
|
1353
|
+
function createPreferencePresetActions(input){return{saveLayoutPreset(value){input.load()
|
|
1354
|
+
const name=normalizePresetName(value)
|
|
1355
|
+
if(Object.keys(input.layoutPresets()).some((candidate)=>candidate.toLocaleLowerCase()===name.toLocaleLowerCase()))
|
|
1356
|
+
throw new Error("A preset with this name already exists")
|
|
1357
|
+
if(Object.keys(input.layoutPresets()).length>=50)
|
|
1358
|
+
throw new Error("You can save at most 50 layout presets")
|
|
1359
|
+
const layout=input.currentLayoutPreset()
|
|
1360
|
+
input.persistLayoutPresets({...input.layoutPresets(),[name]:layout},{name,layout})
|
|
1361
|
+
return name
|
|
1362
|
+
},updateLayoutPreset(name){if(!input.layoutPresets()[name])
|
|
1363
|
+
return false
|
|
1364
|
+
const layout=input.currentLayoutPreset()
|
|
1365
|
+
input.persistLayoutPresets({...input.layoutPresets(),[name]:layout},{name,layout})
|
|
1366
|
+
return true
|
|
1367
|
+
},renameLayoutPreset(current,value){const name=normalizePresetName(value)
|
|
1368
|
+
const preset=input.layoutPresets()[current]
|
|
1369
|
+
if(!preset)
|
|
1370
|
+
throw new Error("Layout preset no longer exists")
|
|
1371
|
+
if(name.toLocaleLowerCase()!==current.toLocaleLowerCase()&&Object.keys(input.layoutPresets()).some((candidate)=>candidate.toLocaleLowerCase()===name.toLocaleLowerCase()))
|
|
1372
|
+
throw new Error("A preset with this name already exists")
|
|
1373
|
+
const next={...input.layoutPresets()}
|
|
1374
|
+
delete next[current]
|
|
1375
|
+
next[name]=preset
|
|
1376
|
+
input.persistLayoutPresets(next,{name,layout:preset,previousName:current})
|
|
1377
|
+
return name
|
|
1378
|
+
},deleteLayoutPreset(name){if(!input.layoutPresets()[name])
|
|
1379
|
+
return false
|
|
1380
|
+
const next={...input.layoutPresets()}
|
|
1381
|
+
delete next[name]
|
|
1382
|
+
input.persistLayoutPresets(next,{name})
|
|
1383
|
+
return true
|
|
1384
|
+
},saveMcpPreset(value,states){input.requireHydration()
|
|
1385
|
+
if(Object.keys(states).length===0)
|
|
1386
|
+
throw new Error("There are no MCP servers to save")
|
|
1387
|
+
const name=normalizePresetName(value)
|
|
1388
|
+
if(Object.keys(input.mcpPresets()).some((candidate)=>candidate.toLocaleLowerCase()===name.toLocaleLowerCase()))
|
|
1389
|
+
throw new Error("A preset with this name already exists")
|
|
1390
|
+
if(Object.keys(input.mcpPresets()).length>=50)
|
|
1391
|
+
throw new Error("You can save at most 50 MCP presets")
|
|
1392
|
+
const preset={...states}
|
|
1393
|
+
input.persistMcpPresets({...input.mcpPresets(),[name]:preset},{operation:"save",name,states:preset})
|
|
1394
|
+
return name
|
|
1395
|
+
},updateMcpPreset(name,states){input.requireHydration()
|
|
1396
|
+
if(!input.mcpPresets()[name])
|
|
1397
|
+
return false
|
|
1398
|
+
if(Object.keys(states).length===0)
|
|
1399
|
+
throw new Error("There are no MCP servers to save")
|
|
1400
|
+
const preset={...states}
|
|
1401
|
+
input.persistMcpPresets({...input.mcpPresets(),[name]:preset},{operation:"update",name,states:preset})
|
|
1402
|
+
return true
|
|
1403
|
+
},renameMcpPreset(current,value){input.requireHydration()
|
|
1404
|
+
const name=normalizePresetName(value)
|
|
1405
|
+
const preset=input.mcpPresets()[current]
|
|
1406
|
+
if(!preset)
|
|
1407
|
+
throw new Error("MCP preset no longer exists")
|
|
1408
|
+
if(name.toLocaleLowerCase()!==current.toLocaleLowerCase()&&Object.keys(input.mcpPresets()).some((candidate)=>candidate.toLocaleLowerCase()===name.toLocaleLowerCase()))
|
|
1409
|
+
throw new Error("A preset with this name already exists")
|
|
1410
|
+
const next={...input.mcpPresets()}
|
|
1411
|
+
delete next[current]
|
|
1412
|
+
next[name]=preset
|
|
1413
|
+
input.persistMcpPresets(next,{operation:"rename",name,previousName:current})
|
|
1414
|
+
return name
|
|
1415
|
+
},deleteMcpPreset(name){input.requireHydration()
|
|
1416
|
+
if(!input.mcpPresets()[name])
|
|
1417
|
+
return false
|
|
1418
|
+
const next={...input.mcpPresets()}
|
|
1419
|
+
delete next[name]
|
|
1420
|
+
input.persistMcpPresets(next,{operation:"delete",name})
|
|
1421
|
+
return true
|
|
1422
|
+
}}}
|
|
1336
1423
|
function toolbarPinKey(pin){return pin.kind==="action"?`action:${pin.id}`:`skill:${pin.location}`
|
|
1337
1424
|
}
|
|
1338
1425
|
function identifier(value){return typeof value==="string"&&/^[a-z][a-z\d-]{0,47}$/u.test(value)
|
|
@@ -1569,14 +1656,6 @@ order=[...layer.layout.order]
|
|
|
1569
1656
|
Object.assign(desiredMcpStates,layer.desiredMcpStates)
|
|
1570
1657
|
}
|
|
1571
1658
|
return{behavior,layout:{sections,expanded,order},desiredMcpStates}}
|
|
1572
|
-
import {randomUUID} from "crypto"
|
|
1573
|
-
import {link,mkdir,readFile,readdir,rename,rm,unlink,writeFile,readFile as readFile2} from "fs/promises"
|
|
1574
|
-
import {join,dirname,join as join2,join as join3} from "path"
|
|
1575
|
-
var LOCK_TIMEOUT_MS=3000
|
|
1576
|
-
function errno(error,code){return error instanceof Error&&"code" in error&&error.code===code
|
|
1577
|
-
}
|
|
1578
|
-
function delay(milliseconds){return new Promise((resolve)=>setTimeout(resolve,milliseconds))
|
|
1579
|
-
}
|
|
1580
1659
|
function parseSkillConfirmations(value){if(!Array.isArray(value))
|
|
1581
1660
|
return []
|
|
1582
1661
|
return [...new Set(value.filter((item)=>typeof item==="string"&&item.length>0))].sort()
|
|
@@ -1723,153 +1802,8 @@ return{global:target.kind==="global"?scope:current.global,worktrees,user:{...ski
|
|
|
1723
1802
|
},...pendingResetAttempt&&{pendingResetAttempt},...typeof (update.user?.autoApprovePermissions??current.user.autoApprovePermissions)==="boolean"&&{autoApprovePermissions:update.user?.autoApprovePermissions??current.user.autoApprovePermissions
|
|
1724
1803
|
}}}}
|
|
1725
1804
|
function targetForLegacyScope(scope){return scope==="global"?{kind:"global"}:{kind:"worktree",key:scope}}
|
|
1726
|
-
function
|
|
1727
|
-
const file=join(directory,"preferences.json")
|
|
1728
|
-
const lock=join(directory,"preferences.lock")
|
|
1729
|
-
let writes=Promise.resolve()
|
|
1730
|
-
async function readLockOwner(){const source=await readFile(lock,"utf8").catch((error)=>{if(errno(error,"ENOENT"))
|
|
1731
|
-
return
|
|
1732
|
-
throw error
|
|
1733
|
-
})
|
|
1734
|
-
if(source===undefined)
|
|
1735
|
-
return
|
|
1736
|
-
try{const value=JSON.parse(source)
|
|
1737
|
-
if(typeof value.token!=="string"||typeof value.pid!=="number")
|
|
1738
|
-
return
|
|
1739
|
-
return{token:value.token,pid:value.pid}} catch{return
|
|
1740
|
-
}}
|
|
1741
|
-
function processIsAlive(pid){try{process.kill(pid,0)
|
|
1742
|
-
return true
|
|
1743
|
-
} catch(error){return !errno(error,"ESRCH")
|
|
1744
|
-
}}
|
|
1745
|
-
async function moveLockToTombstone(suffix){const tombstone=`${lock}.${suffix}.${randomUUID()}`
|
|
1746
|
-
try{await rename(lock,tombstone)
|
|
1747
|
-
} catch(error){if(errno(error,"ENOENT"))
|
|
1748
|
-
return false
|
|
1749
|
-
throw error
|
|
1750
|
-
}
|
|
1751
|
-
await rm(tombstone,{recursive:true,force:true})
|
|
1752
|
-
return true
|
|
1753
|
-
}
|
|
1754
|
-
async function liveRecoveryMarkers(prefix="preferences.lock.recover."){const entries=await readdir(directory)
|
|
1755
|
-
const markers=[]
|
|
1756
|
-
for(const entry of entries){if(!entry.startsWith(prefix)||entry.endsWith(".candidate"))
|
|
1757
|
-
continue
|
|
1758
|
-
const path=join(directory,entry)
|
|
1759
|
-
const markerOwner=await readFile(path,"utf8").then((source)=>JSON.parse(source)).catch(()=>{})
|
|
1760
|
-
if(typeof markerOwner?.pid==="number"&&processIsAlive(markerOwner.pid))
|
|
1761
|
-
markers.push(path)
|
|
1762
|
-
else
|
|
1763
|
-
await unlink(path).catch((error)=>{if(!errno(error,"ENOENT"))
|
|
1764
|
-
throw error
|
|
1765
|
-
})
|
|
1766
|
-
}
|
|
1767
|
-
return markers.sort()
|
|
1768
|
-
}
|
|
1769
|
-
async function reapStaleLock(owner){const token=Buffer.from(owner.token).toString("base64url")
|
|
1770
|
-
const prefix=`preferences.lock.recover.${token}.`
|
|
1771
|
-
const recovery=join(directory,`${prefix}${Date.now().toString().padStart(13, "0")}.${process.pid}.${randomUUID()}`)
|
|
1772
|
-
const markers=await liveRecoveryMarkers(prefix)
|
|
1773
|
-
if(markers.length>0)
|
|
1774
|
-
return false
|
|
1775
|
-
const candidate=`${recovery}.candidate`
|
|
1776
|
-
await writeFile(candidate,JSON.stringify({token:owner.token,pid:process.pid}),{flag:"wx",mode:384})
|
|
1777
|
-
try{await rename(candidate,recovery)
|
|
1778
|
-
await delay(10)
|
|
1779
|
-
const liveMarkers=await liveRecoveryMarkers(prefix)
|
|
1780
|
-
if(liveMarkers[0]!==recovery)
|
|
1781
|
-
return false
|
|
1782
|
-
const current=await readLockOwner()
|
|
1783
|
-
if(current?.token!==owner.token||processIsAlive(current.pid))
|
|
1784
|
-
return false
|
|
1785
|
-
return moveLockToTombstone("stale")
|
|
1786
|
-
} finally{await unlink(candidate).catch((error)=>{if(!errno(error,"ENOENT"))
|
|
1787
|
-
throw error
|
|
1788
|
-
})
|
|
1789
|
-
await unlink(recovery).catch((error)=>{if(!errno(error,"ENOENT"))
|
|
1790
|
-
throw error
|
|
1791
|
-
})
|
|
1792
|
-
}}
|
|
1793
|
-
async function tryAcquireLock(deadline){const token=randomUUID()
|
|
1794
|
-
const candidate=`${lock}.${token}.candidate`
|
|
1795
|
-
let acquired=false
|
|
1796
|
-
let handedOff=false
|
|
1797
|
-
await writeFile(candidate,JSON.stringify({token,pid:process.pid}),{flag:"wx",mode:384})
|
|
1798
|
-
try{try{await link(candidate,lock)
|
|
1799
|
-
acquired=true
|
|
1800
|
-
} catch(error){if(!errno(error,"EEXIST"))
|
|
1801
|
-
throw error
|
|
1802
|
-
const owner=await readLockOwner()
|
|
1803
|
-
if(!owner||processIsAlive(owner.pid))
|
|
1804
|
-
return
|
|
1805
|
-
await reapStaleLock(owner)
|
|
1806
|
-
return
|
|
1807
|
-
}
|
|
1808
|
-
while(true){const markers=await liveRecoveryMarkers()
|
|
1809
|
-
if(markers.length===0)
|
|
1810
|
-
break
|
|
1811
|
-
if(Date.now()>=deadline)
|
|
1812
|
-
return
|
|
1813
|
-
await delay(10)
|
|
1814
|
-
}
|
|
1815
|
-
const currentOwner=await readLockOwner()
|
|
1816
|
-
if(currentOwner?.token!==token)
|
|
1817
|
-
return
|
|
1818
|
-
handedOff=true
|
|
1819
|
-
return async ()=>{const current=await readLockOwner()
|
|
1820
|
-
if(current?.token!==token)
|
|
1821
|
-
throw new Error("Refusing to release a preferences lock owned by another process")
|
|
1822
|
-
await moveLockToTombstone("released")
|
|
1823
|
-
}} finally{if(acquired&&!handedOff){const current=await readLockOwner()
|
|
1824
|
-
if(current?.token===token)
|
|
1825
|
-
await moveLockToTombstone("released")
|
|
1826
|
-
}
|
|
1827
|
-
await unlink(candidate).catch((error)=>{if(!errno(error,"ENOENT"))
|
|
1828
|
-
throw error
|
|
1829
|
-
})
|
|
1830
|
-
}}
|
|
1831
|
-
async function acquireLock(){await mkdir(directory,{recursive:true,mode:448})
|
|
1832
|
-
const deadline=Date.now() + LOCK_TIMEOUT_MS
|
|
1833
|
-
while(true){const release=await tryAcquireLock(deadline)
|
|
1834
|
-
if(release)
|
|
1835
|
-
return release
|
|
1836
|
-
if(Date.now()>=deadline)
|
|
1837
|
-
throw new Error(`Timed out waiting for preferences lock: ${lock}`)
|
|
1838
|
-
await delay(10)
|
|
1839
|
-
}}
|
|
1840
|
-
async function withLock(operation){const release=await acquireLock()
|
|
1841
|
-
try{return await operation()
|
|
1842
|
-
} finally{await release()
|
|
1843
|
-
}}
|
|
1844
|
-
async function read(){const source=await readFile(file,"utf8").catch((error)=>{if(errno(error,"ENOENT"))
|
|
1845
|
-
return
|
|
1846
|
-
throw error
|
|
1847
|
-
})
|
|
1848
|
-
if(source===undefined)
|
|
1849
|
-
return
|
|
1850
|
-
try{return parsePreferencesDocument(JSON.parse(source))
|
|
1851
|
-
} catch(error){if(error instanceof SyntaxError)
|
|
1852
|
-
throw new Error(`Malformed preferences JSON: ${file}`,{cause:error})
|
|
1853
|
-
throw error
|
|
1854
|
-
}}
|
|
1855
|
-
async function write(value){const temporary=`${file}.${process.pid}.${randomUUID()}.tmp`
|
|
1856
|
-
try{await writeFile(temporary,`${JSON.stringify(value)}
|
|
1857
|
-
`,{mode:384})
|
|
1858
|
-
await rename(temporary,file)
|
|
1859
|
-
} finally{await unlink(temporary).catch((error)=>{if(!errno(error,"ENOENT"))
|
|
1860
|
-
throw error
|
|
1861
|
-
})
|
|
1862
|
-
}}
|
|
1863
|
-
function enqueue(operation){const result=writes.then(operation)
|
|
1864
|
-
writes=result.catch(()=>{})
|
|
1865
|
-
return result
|
|
1805
|
+
function skillKey(skill){return skill.location
|
|
1866
1806
|
}
|
|
1867
|
-
return{load(){return withLock(async ()=>await read()??emptyPreferencesDocument())
|
|
1868
|
-
},update(update){return enqueue(()=>withLock(async ()=>{const current=await read()??emptyPreferencesDocument()
|
|
1869
|
-
await write(applyPreferencesUpdate(current,update))
|
|
1870
|
-
}))
|
|
1871
|
-
},async flush(){await writes
|
|
1872
|
-
}}}
|
|
1873
1807
|
function swap(items,first,second){const value=items[first]
|
|
1874
1808
|
items[first]=items[second]
|
|
1875
1809
|
items[second]=value
|
|
@@ -1883,9 +1817,8 @@ return{behavior:scope.behavior,layout:scope.layout,desiredMcpStates:scope.mcp
|
|
|
1883
1817
|
}}
|
|
1884
1818
|
function mergeSessionLayout(base,session){const order=session.order??base?.order
|
|
1885
1819
|
return{sections:{...base?.sections,...session.sections},expanded:{...base?.expanded,...session.expanded},...order&&{order:[...order]}}}
|
|
1886
|
-
function
|
|
1887
|
-
|
|
1888
|
-
},desiredMcpStates:{}}
|
|
1820
|
+
function createPreferencesModel(ports,defaults,store,configuredInput={}){let configured=configuredInput
|
|
1821
|
+
const builtIns=builtInPreferences(defaults)
|
|
1889
1822
|
const [resolved,setResolved]=createSignal5(resolvePreferences({builtIns,pluginOptions:configured}))
|
|
1890
1823
|
const [skippedSkills,setSkippedSkills]=createSignal5(new Set)
|
|
1891
1824
|
const [onboardingCompleted,setOnboardingCompleted]=createSignal5(false)
|
|
@@ -1915,17 +1848,15 @@ let mcpPresetReconciliation=Promise.resolve()
|
|
|
1915
1848
|
let updateRevision=0
|
|
1916
1849
|
let reloading
|
|
1917
1850
|
let isPersistenceWarningShown=false
|
|
1918
|
-
function skillKey(skill){return skill.location
|
|
1919
|
-
}
|
|
1920
1851
|
function showPersistenceWarning(cause){if(isPersistenceWarningShown)
|
|
1921
1852
|
return
|
|
1922
1853
|
isPersistenceWarningShown=true
|
|
1923
|
-
|
|
1854
|
+
ports.notifications.show({variant:"warning",title:"Navigator settings",message:cause instanceof Error?cause.message:"Navigator settings could not be saved"
|
|
1924
1855
|
})
|
|
1925
1856
|
}
|
|
1926
1857
|
function persist(request){request.catch(showPersistenceWarning)
|
|
1927
1858
|
}
|
|
1928
|
-
function validKey(value){try{return
|
|
1859
|
+
function validKey(value){try{return ports.validKey(value)
|
|
1929
1860
|
} catch{return false
|
|
1930
1861
|
}}
|
|
1931
1862
|
function resolveTarget(target,session=true){const worktree=target.kind==="worktree"?document.worktrees[target.key]:undefined
|
|
@@ -1951,13 +1882,16 @@ return{...configured.workspaceProfiles,...document.user.workspaceProfiles}}
|
|
|
1951
1882
|
function scopeSnapshot(target=selectedTarget()){const scope=target.kind==="global"?document.global:document.worktrees[target.key]
|
|
1952
1883
|
return JSON.stringify({layout:scope?.layout,mcp:scope?.mcp,behavior:scope?.behavior})
|
|
1953
1884
|
}
|
|
1954
|
-
function update(change){updateRevision++
|
|
1885
|
+
function update(change,wait=false){updateRevision++
|
|
1955
1886
|
document=applyPreferencesUpdate(document,change)
|
|
1956
|
-
|
|
1957
|
-
|
|
1958
|
-
|
|
1887
|
+
let request
|
|
1888
|
+
if(isHydrated){request=store.update(change)
|
|
1889
|
+
persist(request)
|
|
1890
|
+
} else
|
|
1959
1891
|
pendingUpdates.push(change)
|
|
1960
1892
|
refreshResolved()
|
|
1893
|
+
if(wait)
|
|
1894
|
+
return request??Promise.resolve()
|
|
1961
1895
|
}
|
|
1962
1896
|
function applyDocument(value){document=value
|
|
1963
1897
|
setSkippedSkills(new Set(value.user.skippedSkillConfirmations))
|
|
@@ -2028,13 +1962,6 @@ function setSessionLayout(layout){setTargetSessionLayout(activeTarget(),layout)
|
|
|
2028
1962
|
}
|
|
2029
1963
|
function setSelectedSessionLayout(layout,replace=false){setTargetSessionLayout(selectedTarget(),layout,replace)
|
|
2030
1964
|
}
|
|
2031
|
-
function normalizePresetName(value){const name=value.trim()
|
|
2032
|
-
if(!name)
|
|
2033
|
-
throw new Error("Enter a preset name")
|
|
2034
|
-
if(name.length>64)
|
|
2035
|
-
throw new Error("Preset names can contain at most 64 characters")
|
|
2036
|
-
return name
|
|
2037
|
-
}
|
|
2038
1965
|
function currentLayoutPreset(){const layout=selectedLayoutResolved().layout
|
|
2039
1966
|
return{sections:{...layout.sections},expanded:{...layout.expanded},order:[...layout.order]
|
|
2040
1967
|
}}
|
|
@@ -2058,7 +1985,7 @@ isApplied=!name
|
|
|
2058
1985
|
else if(mcpPreset.operation==="rename"){isApplied=name===mcpPreset.name&&(mcpPreset.previousName===mcpPreset.name||!actual[mcpPreset.previousName])
|
|
2059
1986
|
} else{isApplied=Boolean(name)&&Object.keys(actual[name]).length===Object.keys(mcpPreset.states).length&&Object.entries(mcpPreset.states).every(([server,state])=>actual[name][server]===state)
|
|
2060
1987
|
}
|
|
2061
|
-
if(!isApplied){
|
|
1988
|
+
if(!isApplied){ports.notifications.show({variant:"warning",title:"MCP presets",message:"Preset changed in another OpenCode instance; reloaded saved presets"
|
|
2062
1989
|
})
|
|
2063
1990
|
}}).catch(showPersistenceWarning)
|
|
2064
1991
|
}
|
|
@@ -2094,13 +2021,14 @@ return
|
|
|
2094
2021
|
setAutoApprovePermissions(value)
|
|
2095
2022
|
update({user:{autoApprovePermissions:value}})
|
|
2096
2023
|
}
|
|
2024
|
+
function codexBindingUpdate(providerID,connectionID,accountID){setCodexAccountBindings((bindings)=>changeCodexBinding(bindings,{providerID,connectionID},accountID))
|
|
2025
|
+
return{user:{codexAccountBinding:{providerID,connectionID,accountID}}}}
|
|
2097
2026
|
function changeCodexConnectionBinding(providerID,connectionID,accountID){if(!isHydrated){load().then(()=>changeCodexConnectionBinding(providerID,connectionID,accountID))
|
|
2098
2027
|
return
|
|
2099
2028
|
}
|
|
2100
2029
|
if(!providerID)
|
|
2101
2030
|
return
|
|
2102
|
-
|
|
2103
|
-
update({user:{codexAccountBinding:{providerID,connectionID,accountID}}})
|
|
2031
|
+
update(codexBindingUpdate(providerID,connectionID,accountID))
|
|
2104
2032
|
}
|
|
2105
2033
|
function toggleFavoriteMcpServer(name){if(!isHydrated){load().then(()=>toggleFavoriteMcpServer(name))
|
|
2106
2034
|
return
|
|
@@ -2126,10 +2054,18 @@ next.add(id)
|
|
|
2126
2054
|
setFavoriteQuickActions(next)
|
|
2127
2055
|
update({user:{favoriteQuickAction:{id,favorite:next.has(id)}}})
|
|
2128
2056
|
}
|
|
2129
|
-
return{
|
|
2057
|
+
return{setConfiguredDefaults(next){batch(()=>{configured=next
|
|
2058
|
+
setLayoutPresets({...configured.layoutPresets,...document.user.layoutPresets})
|
|
2059
|
+
setMcpPresets({...configured.mcpPresets,...document.user.mcpPresets})
|
|
2060
|
+
setMcpServerGroups({...configured.mcpServerGroups,...document.user.mcpServerGroups})
|
|
2061
|
+
refreshResolved()
|
|
2062
|
+
})
|
|
2063
|
+
},sections:()=>resolved().layout.sections,toolbarPins(){revision()
|
|
2130
2064
|
return document.user.toolbarPins??[]
|
|
2131
2065
|
},changeToolbarPin(change){requireHydration()
|
|
2132
2066
|
update({user:{toolbarPin:change}})
|
|
2067
|
+
},saveToolbarPin(change){requireHydration()
|
|
2068
|
+
return update({user:{toolbarPin:change}},true)
|
|
2133
2069
|
},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()
|
|
2134
2070
|
return resolveTarget(targetForScope(scope),false).behavior.startInChat
|
|
2135
2071
|
},cornerFont:()=>resolved().behavior.cornerFont,lspIconStyle:()=>resolved().behavior.lspIconStyle,rowDensity:()=>resolved().behavior.rowDensity,toolbarOverflow:()=>resolved().behavior.toolbarOverflow,selectedToolbarOverflow:()=>selectedResolved().behavior.toolbarOverflow,toggleToolbarOverflow(){load()
|
|
@@ -2183,7 +2119,16 @@ throw new Error("MCP preset no longer exists")
|
|
|
2183
2119
|
update({user:{workspaceProfile:{layout,mcp}}})
|
|
2184
2120
|
},favoriteSkills,favoriteMcpServers,favoriteQuickActions,toggleFavoriteMcpServer,toggleFavoriteQuickAction,recentSkills,recentQuickActions,mcpServerGroups,setMcpServerGroup(name,value){setMcpServerGroups(assignGroup(mcpServerGroups(),name,value))
|
|
2185
2121
|
update({user:{mcpServerGroup:{name,group:value}}})
|
|
2186
|
-
},skillGroups,setSkillGroup:changeSkillGroup,autoApprovePermissions,setAutoApprovePermissions:changeAutoApprovePermissions,codexAccountForModel:(providerID,modelID)=>codexBindingAccount(codexAccountBindings(),{providerID},modelID),setCodexAccountBinding:(providerID,_modelID,accountID)=>changeCodexConnectionBinding(providerID,undefined,accountID),codexAccountForConnection:(providerID,connectionID,modelID)=>codexBindingAccount(codexAccountBindings(),{providerID,connectionID},modelID),setCodexConnectionBinding:changeCodexConnectionBinding,
|
|
2122
|
+
},skillGroups,setSkillGroup:changeSkillGroup,autoApprovePermissions,setAutoApprovePermissions:changeAutoApprovePermissions,codexAccountForModel:(providerID,modelID)=>codexBindingAccount(codexAccountBindings(),{providerID},modelID),setCodexAccountBinding:(providerID,_modelID,accountID)=>changeCodexConnectionBinding(providerID,undefined,accountID),codexAccountForConnection:(providerID,connectionID,modelID)=>codexBindingAccount(codexAccountBindings(),{providerID,connectionID},modelID),setCodexConnectionBinding:changeCodexConnectionBinding,async saveCodexConnectionBinding(providerID,connectionID,accountID){requireHydration()
|
|
2123
|
+
if(!providerID||!accountID)
|
|
2124
|
+
throw new Error("A provider and verified account are required")
|
|
2125
|
+
updateRevision++
|
|
2126
|
+
const request=store.update({user:{codexAccountBinding:{providerID,connectionID,accountID}}})
|
|
2127
|
+
persist(request)
|
|
2128
|
+
await request
|
|
2129
|
+
document=applyPreferencesUpdate(document,codexBindingUpdate(providerID,connectionID,accountID))
|
|
2130
|
+
refreshResolved()
|
|
2131
|
+
},pendingResetAttempt,async beginResetAttempt(attempt){await load()
|
|
2187
2132
|
await store.update({user:{pendingResetAttempt:attempt}})
|
|
2188
2133
|
const current=await store.load()
|
|
2189
2134
|
setPendingResetAttempt(current.user.pendingResetAttempt)
|
|
@@ -2236,6 +2181,9 @@ setSessionLayout({order})
|
|
|
2236
2181
|
},toggleSelectedSection(name){load()
|
|
2237
2182
|
const layout=resolveTarget(selectedTarget()).layout
|
|
2238
2183
|
setSelectedSessionLayout({sections:{[name]:!layout.sections[name]}})
|
|
2184
|
+
},toggleSelectedSectionExpanded(name){load()
|
|
2185
|
+
const layout=resolveTarget(selectedTarget()).layout
|
|
2186
|
+
setSelectedSessionLayout({expanded:{[name]:!layout.expanded[name]}})
|
|
2239
2187
|
},moveSelectedSection(name,direction){load()
|
|
2240
2188
|
const layout=resolveTarget(selectedTarget()).layout
|
|
2241
2189
|
const order=[...layout.order]
|
|
@@ -2248,76 +2196,8 @@ setSelectedSessionLayout({order})
|
|
|
2248
2196
|
},previewLayoutPreset(preset){return layoutPresetPreview(selectedLayoutResolved().layout,preset)
|
|
2249
2197
|
},applyLayoutPreset(preset){load()
|
|
2250
2198
|
setSelectedSessionLayout(layoutPresetPreview(selectedLayoutResolved().layout,preset).next,true)
|
|
2251
|
-
}
|
|
2252
|
-
|
|
2253
|
-
if(Object.keys(layoutPresets()).some((candidate)=>candidate.toLocaleLowerCase()===name.toLocaleLowerCase())){throw new Error("A preset with this name already exists")
|
|
2254
|
-
}
|
|
2255
|
-
if(Object.keys(layoutPresets()).length>=50)
|
|
2256
|
-
throw new Error("You can save at most 50 layout presets")
|
|
2257
|
-
const layout=currentLayoutPreset()
|
|
2258
|
-
persistLayoutPresets({...layoutPresets(),[name]:layout},{name,layout})
|
|
2259
|
-
return name
|
|
2260
|
-
},updateLayoutPreset(name){if(!layoutPresets()[name])
|
|
2261
|
-
return false
|
|
2262
|
-
const layout=currentLayoutPreset()
|
|
2263
|
-
persistLayoutPresets({...layoutPresets(),[name]:layout},{name,layout})
|
|
2264
|
-
return true
|
|
2265
|
-
},renameLayoutPreset(current,value){const name=normalizePresetName(value)
|
|
2266
|
-
const preset=layoutPresets()[current]
|
|
2267
|
-
if(!preset)
|
|
2268
|
-
throw new Error("Layout preset no longer exists")
|
|
2269
|
-
if(name.toLocaleLowerCase()!==current.toLocaleLowerCase()&&Object.keys(layoutPresets()).some((candidate)=>candidate.toLocaleLowerCase()===name.toLocaleLowerCase())){throw new Error("A preset with this name already exists")
|
|
2270
|
-
}
|
|
2271
|
-
const next={...layoutPresets()}
|
|
2272
|
-
delete next[current]
|
|
2273
|
-
next[name]=preset
|
|
2274
|
-
persistLayoutPresets(next,{name,layout:preset,previousName:current})
|
|
2275
|
-
return name
|
|
2276
|
-
},deleteLayoutPreset(name){if(!layoutPresets()[name])
|
|
2277
|
-
return false
|
|
2278
|
-
const next={...layoutPresets()}
|
|
2279
|
-
delete next[name]
|
|
2280
|
-
persistLayoutPresets(next,{name})
|
|
2281
|
-
return true
|
|
2282
|
-
},saveMcpPreset(value,states){requireHydration()
|
|
2283
|
-
if(Object.keys(states).length===0)
|
|
2284
|
-
throw new Error("There are no MCP servers to save")
|
|
2285
|
-
const name=normalizePresetName(value)
|
|
2286
|
-
if(Object.keys(mcpPresets()).some((candidate)=>candidate.toLocaleLowerCase()===name.toLocaleLowerCase())){throw new Error("A preset with this name already exists")
|
|
2287
|
-
}
|
|
2288
|
-
if(Object.keys(mcpPresets()).length>=50)
|
|
2289
|
-
throw new Error("You can save at most 50 MCP presets")
|
|
2290
|
-
const preset={...states}
|
|
2291
|
-
persistMcpPresets({...mcpPresets(),[name]:preset},{operation:"save",name,states:preset})
|
|
2292
|
-
return name
|
|
2293
|
-
},updateMcpPreset(name,states){requireHydration()
|
|
2294
|
-
if(!mcpPresets()[name])
|
|
2295
|
-
return false
|
|
2296
|
-
if(Object.keys(states).length===0)
|
|
2297
|
-
throw new Error("There are no MCP servers to save")
|
|
2298
|
-
const preset={...states}
|
|
2299
|
-
persistMcpPresets({...mcpPresets(),[name]:preset},{operation:"update",name,states:preset})
|
|
2300
|
-
return true
|
|
2301
|
-
},renameMcpPreset(current,value){requireHydration()
|
|
2302
|
-
const name=normalizePresetName(value)
|
|
2303
|
-
const preset=mcpPresets()[current]
|
|
2304
|
-
if(!preset)
|
|
2305
|
-
throw new Error("MCP preset no longer exists")
|
|
2306
|
-
if(name.toLocaleLowerCase()!==current.toLocaleLowerCase()&&Object.keys(mcpPresets()).some((candidate)=>candidate.toLocaleLowerCase()===name.toLocaleLowerCase())){throw new Error("A preset with this name already exists")
|
|
2307
|
-
}
|
|
2308
|
-
const next={...mcpPresets()}
|
|
2309
|
-
delete next[current]
|
|
2310
|
-
next[name]=preset
|
|
2311
|
-
persistMcpPresets(next,{operation:"rename",name,previousName:current})
|
|
2312
|
-
return name
|
|
2313
|
-
},deleteMcpPreset(name){requireHydration()
|
|
2314
|
-
if(!mcpPresets()[name])
|
|
2315
|
-
return false
|
|
2316
|
-
const next={...mcpPresets()}
|
|
2317
|
-
delete next[name]
|
|
2318
|
-
persistMcpPresets(next,{operation:"delete",name})
|
|
2319
|
-
return true
|
|
2320
|
-
},async saveLayoutAsDefault(){await load()
|
|
2199
|
+
},...createPreferencePresetActions({load,requireHydration,layoutPresets,mcpPresets,currentLayoutPreset,persistLayoutPresets,persistMcpPresets
|
|
2200
|
+
}),async saveLayoutAsDefault(){await load()
|
|
2321
2201
|
const target=selectedTarget()
|
|
2322
2202
|
const layout=resolveTarget(target).layout
|
|
2323
2203
|
updateRevision++
|
|
@@ -2380,6 +2260,9 @@ update({target:targetForScope(scope),mcp:{name,state}})
|
|
|
2380
2260
|
},setDesiredMcpStates(scope,states){load()
|
|
2381
2261
|
update({target:targetForScope(scope),mcp:{states}})
|
|
2382
2262
|
}}}
|
|
2263
|
+
function createPreferencesController(api,defaults,store,configured={}){return createPreferencesModel({notifications:{show:(input)=>api.ui.toast({...input,duration:4000})},validKey:(value)=>api.keymap?.parseKeySequence?api.keymap.parseKeySequence(value).length>0:Boolean(value.trim())
|
|
2264
|
+
},defaults,store,configured)
|
|
2265
|
+
}
|
|
2383
2266
|
function record2(value){if(!value||typeof value!=="object"||Array.isArray(value))
|
|
2384
2267
|
return
|
|
2385
2268
|
return value
|
|
@@ -2414,17 +2297,173 @@ function legacyDefaults(config){const{sections,sectionOrder,...behavior}=config
|
|
|
2414
2297
|
return{behavior,layout:{sections,expanded:{},...sectionOrder&&{order:sectionOrder}}}}
|
|
2415
2298
|
function configuredDefaultsFromPluginOptions(options){return mergeConfiguredDefaults(legacyDefaults(pluginConfig(options)),parseConfiguredDefaults(options??{}))
|
|
2416
2299
|
}
|
|
2300
|
+
import {randomUUID} from "crypto"
|
|
2301
|
+
import {link,mkdir,readFile,readdir,rename,rm,unlink,writeFile,readFile as readFile2} from "fs/promises"
|
|
2302
|
+
import {join,dirname,join as join2,join as join3} from "path"
|
|
2303
|
+
var LOCK_TIMEOUT_MS=3000
|
|
2304
|
+
function errno(error,code){return error instanceof Error&&"code" in error&&error.code===code
|
|
2305
|
+
}
|
|
2306
|
+
function delay(milliseconds){return new Promise((resolve)=>setTimeout(resolve,milliseconds))
|
|
2307
|
+
}
|
|
2308
|
+
function createPreferencesStore(stateDirectory){const directory=join(stateDirectory,LEGACY_PLUGIN_ID)
|
|
2309
|
+
const file=join(directory,"preferences.json")
|
|
2310
|
+
const lock=join(directory,"preferences.lock")
|
|
2311
|
+
let writes=Promise.resolve()
|
|
2312
|
+
async function readLockOwner(){const source=await readFile(lock,"utf8").catch((error)=>{if(errno(error,"ENOENT"))
|
|
2313
|
+
return
|
|
2314
|
+
throw error
|
|
2315
|
+
})
|
|
2316
|
+
if(source===undefined)
|
|
2317
|
+
return
|
|
2318
|
+
try{const value=JSON.parse(source)
|
|
2319
|
+
if(typeof value.token!=="string"||typeof value.pid!=="number")
|
|
2320
|
+
return
|
|
2321
|
+
return{token:value.token,pid:value.pid}} catch{return
|
|
2322
|
+
}}
|
|
2323
|
+
function processIsAlive(pid){try{process.kill(pid,0)
|
|
2324
|
+
return true
|
|
2325
|
+
} catch(error){return !errno(error,"ESRCH")
|
|
2326
|
+
}}
|
|
2327
|
+
async function moveLockToTombstone(suffix){const tombstone=`${lock}.${suffix}.${randomUUID()}`
|
|
2328
|
+
try{await rename(lock,tombstone)
|
|
2329
|
+
} catch(error){if(errno(error,"ENOENT"))
|
|
2330
|
+
return false
|
|
2331
|
+
throw error
|
|
2332
|
+
}
|
|
2333
|
+
await rm(tombstone,{recursive:true,force:true})
|
|
2334
|
+
return true
|
|
2335
|
+
}
|
|
2336
|
+
async function liveRecoveryMarkers(prefix="preferences.lock.recover."){const entries=await readdir(directory)
|
|
2337
|
+
const markers=[]
|
|
2338
|
+
for(const entry of entries){if(!entry.startsWith(prefix)||entry.endsWith(".candidate"))
|
|
2339
|
+
continue
|
|
2340
|
+
const path=join(directory,entry)
|
|
2341
|
+
const markerOwner=await readFile(path,"utf8").then((source)=>JSON.parse(source)).catch(()=>{})
|
|
2342
|
+
if(typeof markerOwner?.pid==="number"&&processIsAlive(markerOwner.pid))
|
|
2343
|
+
markers.push(path)
|
|
2344
|
+
else
|
|
2345
|
+
await unlink(path).catch((error)=>{if(!errno(error,"ENOENT"))
|
|
2346
|
+
throw error
|
|
2347
|
+
})
|
|
2348
|
+
}
|
|
2349
|
+
return markers.sort()
|
|
2350
|
+
}
|
|
2351
|
+
async function reapStaleLock(owner){const token=Buffer.from(owner.token).toString("base64url")
|
|
2352
|
+
const prefix=`preferences.lock.recover.${token}.`
|
|
2353
|
+
const recovery=join(directory,`${prefix}${Date.now().toString().padStart(13, "0")}.${process.pid}.${randomUUID()}`)
|
|
2354
|
+
const markers=await liveRecoveryMarkers(prefix)
|
|
2355
|
+
if(markers.length>0)
|
|
2356
|
+
return false
|
|
2357
|
+
const candidate=`${recovery}.candidate`
|
|
2358
|
+
await writeFile(candidate,JSON.stringify({token:owner.token,pid:process.pid}),{flag:"wx",mode:384})
|
|
2359
|
+
try{await rename(candidate,recovery)
|
|
2360
|
+
await delay(10)
|
|
2361
|
+
const liveMarkers=await liveRecoveryMarkers(prefix)
|
|
2362
|
+
if(liveMarkers[0]!==recovery)
|
|
2363
|
+
return false
|
|
2364
|
+
const current=await readLockOwner()
|
|
2365
|
+
if(current?.token!==owner.token||processIsAlive(current.pid))
|
|
2366
|
+
return false
|
|
2367
|
+
return moveLockToTombstone("stale")
|
|
2368
|
+
} finally{await unlink(candidate).catch((error)=>{if(!errno(error,"ENOENT"))
|
|
2369
|
+
throw error
|
|
2370
|
+
})
|
|
2371
|
+
await unlink(recovery).catch((error)=>{if(!errno(error,"ENOENT"))
|
|
2372
|
+
throw error
|
|
2373
|
+
})
|
|
2374
|
+
}}
|
|
2375
|
+
async function tryAcquireLock(deadline){const token=randomUUID()
|
|
2376
|
+
const candidate=`${lock}.${token}.candidate`
|
|
2377
|
+
let acquired=false
|
|
2378
|
+
let handedOff=false
|
|
2379
|
+
await writeFile(candidate,JSON.stringify({token,pid:process.pid}),{flag:"wx",mode:384})
|
|
2380
|
+
try{try{await link(candidate,lock)
|
|
2381
|
+
acquired=true
|
|
2382
|
+
} catch(error){if(!errno(error,"EEXIST"))
|
|
2383
|
+
throw error
|
|
2384
|
+
const owner=await readLockOwner()
|
|
2385
|
+
if(!owner||processIsAlive(owner.pid))
|
|
2386
|
+
return
|
|
2387
|
+
await reapStaleLock(owner)
|
|
2388
|
+
return
|
|
2389
|
+
}
|
|
2390
|
+
while(true){const markers=await liveRecoveryMarkers()
|
|
2391
|
+
if(markers.length===0)
|
|
2392
|
+
break
|
|
2393
|
+
if(Date.now()>=deadline)
|
|
2394
|
+
return
|
|
2395
|
+
await delay(10)
|
|
2396
|
+
}
|
|
2397
|
+
const currentOwner=await readLockOwner()
|
|
2398
|
+
if(currentOwner?.token!==token)
|
|
2399
|
+
return
|
|
2400
|
+
handedOff=true
|
|
2401
|
+
return async ()=>{const current=await readLockOwner()
|
|
2402
|
+
if(current?.token!==token)
|
|
2403
|
+
throw new Error("Refusing to release a preferences lock owned by another process")
|
|
2404
|
+
await moveLockToTombstone("released")
|
|
2405
|
+
}} finally{if(acquired&&!handedOff){const current=await readLockOwner()
|
|
2406
|
+
if(current?.token===token)
|
|
2407
|
+
await moveLockToTombstone("released")
|
|
2408
|
+
}
|
|
2409
|
+
await unlink(candidate).catch((error)=>{if(!errno(error,"ENOENT"))
|
|
2410
|
+
throw error
|
|
2411
|
+
})
|
|
2412
|
+
}}
|
|
2413
|
+
async function acquireLock(){await mkdir(directory,{recursive:true,mode:448})
|
|
2414
|
+
const deadline=Date.now() + LOCK_TIMEOUT_MS
|
|
2415
|
+
while(true){const release=await tryAcquireLock(deadline)
|
|
2416
|
+
if(release)
|
|
2417
|
+
return release
|
|
2418
|
+
if(Date.now()>=deadline)
|
|
2419
|
+
throw new Error(`Timed out waiting for preferences lock: ${lock}`)
|
|
2420
|
+
await delay(10)
|
|
2421
|
+
}}
|
|
2422
|
+
async function withLock(operation){const release=await acquireLock()
|
|
2423
|
+
try{return await operation()
|
|
2424
|
+
} finally{await release()
|
|
2425
|
+
}}
|
|
2426
|
+
async function read(){const source=await readFile(file,"utf8").catch((error)=>{if(errno(error,"ENOENT"))
|
|
2427
|
+
return
|
|
2428
|
+
throw error
|
|
2429
|
+
})
|
|
2430
|
+
if(source===undefined)
|
|
2431
|
+
return
|
|
2432
|
+
try{return parsePreferencesDocument(JSON.parse(source))
|
|
2433
|
+
} catch(error){if(error instanceof SyntaxError)
|
|
2434
|
+
throw new Error(`Malformed preferences JSON: ${file}`,{cause:error})
|
|
2435
|
+
throw error
|
|
2436
|
+
}}
|
|
2437
|
+
async function write(value){const temporary=`${file}.${process.pid}.${randomUUID()}.tmp`
|
|
2438
|
+
try{await writeFile(temporary,`${JSON.stringify(value)}
|
|
2439
|
+
`,{mode:384})
|
|
2440
|
+
await rename(temporary,file)
|
|
2441
|
+
} finally{await unlink(temporary).catch((error)=>{if(!errno(error,"ENOENT"))
|
|
2442
|
+
throw error
|
|
2443
|
+
})
|
|
2444
|
+
}}
|
|
2445
|
+
function enqueue(operation){const result=writes.then(operation)
|
|
2446
|
+
writes=result.catch(()=>{})
|
|
2447
|
+
return result
|
|
2448
|
+
}
|
|
2449
|
+
return{load(){return withLock(async ()=>await read()??emptyPreferencesDocument())
|
|
2450
|
+
},update(update){return enqueue(()=>withLock(async ()=>{const current=await read()??emptyPreferencesDocument()
|
|
2451
|
+
await write(applyPreferencesUpdate(current,update))
|
|
2452
|
+
}))
|
|
2453
|
+
},async flush(){await writes
|
|
2454
|
+
}}}
|
|
2417
2455
|
|
|
2418
|
-
function
|
|
2456
|
+
function createSkillModel(options){const{source,lifecycle}=options
|
|
2457
|
+
const [skills,setSkills]=createSignal6({})
|
|
2419
2458
|
const refreshing=new Map
|
|
2420
2459
|
const targets=new Map
|
|
2421
|
-
const requests=createRequestState(
|
|
2422
|
-
const promptRequests=createRequestState(
|
|
2460
|
+
const requests=createRequestState(lifecycle.signal)
|
|
2461
|
+
const promptRequests=createRequestState(lifecycle.signal)
|
|
2423
2462
|
let activeTarget
|
|
2424
2463
|
let leases=new Set
|
|
2425
|
-
function target(){return
|
|
2464
|
+
function target(){return options.target()
|
|
2426
2465
|
}
|
|
2427
|
-
function list(current=target()){return source?source.list(current):skills()[current.key]??[]
|
|
2466
|
+
function list(current=target()){return options.cache==="source"?source.list(current):skills()[current.key]??[]
|
|
2428
2467
|
}
|
|
2429
2468
|
function error(current=target()){return requests.state(current.key).error?.message
|
|
2430
2469
|
}
|
|
@@ -2435,8 +2474,8 @@ targets.set(current.key,current)
|
|
|
2435
2474
|
const requestState=requests.start(current.key,"refresh skills",current.key in skills(),force)
|
|
2436
2475
|
if(!requestState)
|
|
2437
2476
|
return pending
|
|
2438
|
-
const request=
|
|
2439
|
-
if(
|
|
2477
|
+
const request=source.refresh(current,force,requestState.signal).then((data)=>{const items=[...data].sort((a,b)=>a.name.localeCompare(b.name))
|
|
2478
|
+
if(options.cache==="model"&&requestState.isCurrent())
|
|
2440
2479
|
setSkills((value)=>({...value,[current.key]:items}))
|
|
2441
2480
|
requestState.succeed()
|
|
2442
2481
|
return items
|
|
@@ -2449,9 +2488,9 @@ refreshing.delete(current.key)
|
|
|
2449
2488
|
refreshing.set(current.key,request)
|
|
2450
2489
|
return request
|
|
2451
2490
|
}
|
|
2452
|
-
const unsubscribe=
|
|
2491
|
+
const unsubscribe=options.onReconnect(()=>{for(const current of targets.values()){retryBackgroundRefresh(()=>refresh(current),{signal:lifecycle.signal}).catch(()=>{})
|
|
2453
2492
|
}})
|
|
2454
|
-
|
|
2493
|
+
lifecycle.onDispose(unsubscribe)
|
|
2455
2494
|
return{list,error,refresh,target,state(current=target()){return requests.state(current.key)
|
|
2456
2495
|
},retry(current=target()){return refresh(current,true)
|
|
2457
2496
|
},activate(current=target()){targets.set(current.key,current)
|
|
@@ -2477,15 +2516,24 @@ throw new DOMException("Sidebar context changed","AbortError")
|
|
|
2477
2516
|
const request=promptRequests.start(current.key,"insert skill",false,true)
|
|
2478
2517
|
if(!request)
|
|
2479
2518
|
return false
|
|
2480
|
-
try{const result=
|
|
2519
|
+
try{const result=selected?await source.use(current,selected,request.signal):await options.useNamed?.(current,name,request.signal)
|
|
2481
2520
|
if(!request.isCurrent())
|
|
2482
2521
|
return false
|
|
2483
2522
|
request.succeed()
|
|
2484
|
-
return result
|
|
2523
|
+
return result??false
|
|
2485
2524
|
} catch(error_){request.fail(error_)
|
|
2486
2525
|
throw error_
|
|
2487
2526
|
} finally{request.finish()
|
|
2488
2527
|
}}}}
|
|
2528
|
+
function createSkillController(api,source){const useNamed=async (target,name,signal)=>{const result=await api.client.tui.appendPrompt({...target.routing,text:`/${name} `},{throwOnError:true,signal})
|
|
2529
|
+
return result.data??false
|
|
2530
|
+
}
|
|
2531
|
+
return createSkillModel({lifecycle:api.lifecycle,target:()=>currentLocation(api),cache:source?"source":"model",source:source??{list:()=>[],async refresh(target,_force,signal){const result=await api.client.app.skills(target.routing,{throwOnError:true,signal})
|
|
2532
|
+
return result.data??[]
|
|
2533
|
+
},use:(target,skill,signal)=>useNamed(target,skill.name,signal)
|
|
2534
|
+
},onReconnect:(listener)=>api.event.on("server.connected",listener),useNamed
|
|
2535
|
+
})
|
|
2536
|
+
}
|
|
2489
2537
|
var BUCKET_RANK2={Favorites:0,Ungrouped:2}
|
|
2490
2538
|
function buildSkillGroupedView(items,favorites,groups,recent){return items.map((item)=>({...item,assignedGroup:groups[item.location],bucket:favorites.has(item.location)?"Favorites":groups[item.location]??"Ungrouped"
|
|
2491
2539
|
})).sort((left,right)=>{const rank=(BUCKET_RANK2[left.bucket]??1)-(BUCKET_RANK2[right.bucket]??1)
|
|
@@ -2739,34 +2787,40 @@ return "Skill source changed"
|
|
|
2739
2787
|
return "Multiple sources share this skill name"
|
|
2740
2788
|
return
|
|
2741
2789
|
}
|
|
2742
|
-
function
|
|
2743
|
-
}}
|
|
2790
|
+
function createSkillActivation(input){const skill={...input.skill}
|
|
2744
2791
|
const target=input.controller.target()
|
|
2745
|
-
|
|
2746
|
-
const current=()=>target.key===input.controller.target().key&&route===JSON.stringify(input.api.route.current)
|
|
2747
|
-
const report=(error)=>{if(!isAbortError(error))
|
|
2748
|
-
input.api.ui.toast({variant:"error",title:"Skills",message:String(error),duration:5000
|
|
2749
|
-
})
|
|
2750
|
-
}
|
|
2751
|
-
function check(){if(!current())
|
|
2792
|
+
function check(){if(!input.current()||target.key!==input.controller.target().key)
|
|
2752
2793
|
throw new DOMException("Skill target changed; choose it again","AbortError")
|
|
2753
|
-
const reason=skillUnavailable(input.controller,
|
|
2794
|
+
const reason=skillUnavailable(input.controller,skill)
|
|
2754
2795
|
if(reason)
|
|
2755
2796
|
throw new Error(reason)
|
|
2756
2797
|
}
|
|
2757
|
-
async
|
|
2798
|
+
return{skill,check,shouldConfirm:()=>input.access.shouldConfirmSkill(skill),async run(skip=false){check()
|
|
2758
2799
|
if(skip)
|
|
2759
|
-
input.access.skipSkillConfirmation(
|
|
2800
|
+
input.access.skipSkillConfirmation(skill)
|
|
2760
2801
|
input.beforeInsert?.()
|
|
2761
|
-
|
|
2762
|
-
|
|
2802
|
+
const inserted=await input.controller.use(target,skill.name,skill)
|
|
2803
|
+
if(inserted)
|
|
2804
|
+
await input.access.recordSkillUse?.(skill)
|
|
2805
|
+
return inserted
|
|
2806
|
+
}}}
|
|
2807
|
+
function activateSkill(input){input={...input,skill:{...input.skill
|
|
2808
|
+
}}
|
|
2809
|
+
const route=JSON.stringify(input.api.route.current)
|
|
2810
|
+
const activation=createSkillActivation({...input,current:()=>route===JSON.stringify(input.api.route.current)
|
|
2811
|
+
})
|
|
2812
|
+
const report=(error)=>{if(!isAbortError(error))
|
|
2813
|
+
input.api.ui.toast({variant:"error",title:"Skills",message:String(error),duration:5000
|
|
2814
|
+
})
|
|
2815
|
+
}
|
|
2816
|
+
async function insert(skip=false){try{await activation.run(skip)
|
|
2763
2817
|
} catch(error){report(error)
|
|
2764
2818
|
}}
|
|
2765
|
-
try{check()
|
|
2819
|
+
try{activation.check()
|
|
2766
2820
|
} catch(error){report(error)
|
|
2767
2821
|
return
|
|
2768
2822
|
}
|
|
2769
|
-
if(!
|
|
2823
|
+
if(!activation.shouldConfirm()){insert()
|
|
2770
2824
|
return
|
|
2771
2825
|
}
|
|
2772
2826
|
input.dialogs.open(()=>_$createComponent(SkillDialog,{get api(){return input.api
|
|
@@ -2819,7 +2873,7 @@ return
|
|
|
2819
2873
|
const isCancelled=error?.name==="MessageAbortedError"
|
|
2820
2874
|
const data=error&&"data" in error?error.data:undefined
|
|
2821
2875
|
const fallbackMessage=isCancelled?"Session aborted":"Session error"
|
|
2822
|
-
const message=data&&"message" in data&&typeof data.message==="string"?data.message:fallbackMessage
|
|
2876
|
+
const message=data&&typeof data==="object"&&"message" in data&&typeof data.message==="string"?data.message:fallbackMessage
|
|
2823
2877
|
const next={...run,startedAt:Math.min(run.startedAt,at),outcome:isCancelled?"cancelled":"error",errorMessage:message
|
|
2824
2878
|
}
|
|
2825
2879
|
if(value.active.has(sessionID))
|
|
@@ -2842,7 +2896,7 @@ return targets.get(key)?.recent??[]
|
|
|
2842
2896
|
var POLL_INTERVAL_MS=5000
|
|
2843
2897
|
function activeStatus(status){return status?.type==="busy"||status?.type==="retry"
|
|
2844
2898
|
}
|
|
2845
|
-
function
|
|
2899
|
+
function createSubagentModel(options){const source=options.source
|
|
2846
2900
|
const now=options.now??Date.now
|
|
2847
2901
|
const history=createSubagentHistory({now})
|
|
2848
2902
|
const [children,setChildren]=createSignal8({})
|
|
@@ -2853,14 +2907,13 @@ const [unavailable,setUnavailable]=createSignal8({})
|
|
|
2853
2907
|
const targets=new Map
|
|
2854
2908
|
const remoteFailures=new Map
|
|
2855
2909
|
const remoteRetryAt=new Map
|
|
2856
|
-
const requests=createRequestState(
|
|
2910
|
+
const requests=createRequestState(options.lifecycle.signal)
|
|
2857
2911
|
let activeTarget
|
|
2912
|
+
let leases=new Set
|
|
2858
2913
|
let pollTimer
|
|
2859
|
-
const snapshots=()=>source?Object.fromEntries([...targets].map(([key,current])=>[key,source.list(current.parentID)])):children()
|
|
2860
|
-
function target(parentID){
|
|
2861
|
-
|
|
2862
|
-
const workspace=parent?.workspaceID
|
|
2863
|
-
return{key:JSON.stringify([parentID,directory,workspace??null]),parentID,routing:{directory,...workspace&&{workspace}}}}
|
|
2914
|
+
const snapshots=()=>options.cache==="source"?Object.fromEntries([...targets].map(([key,current])=>[key,source.list(current.parentID)])):children()
|
|
2915
|
+
function target(parentID){return options.target(parentID)
|
|
2916
|
+
}
|
|
2864
2917
|
function applySession(items,parentID,mutation){const next=items.filter((item)=>item.id!==(mutation.type==="upsert"?mutation.info.id:mutation.sessionID))
|
|
2865
2918
|
if(mutation.type==="upsert"&&mutation.info.parentID===parentID)
|
|
2866
2919
|
next.push(mutation.info)
|
|
@@ -2875,19 +2928,19 @@ history.remove(key,sessionID)
|
|
|
2875
2928
|
}
|
|
2876
2929
|
for(const journal of journals)
|
|
2877
2930
|
journal.sessions.push(mutation)
|
|
2878
|
-
if(
|
|
2931
|
+
if(options.cache==="model")
|
|
2879
2932
|
setChildren((current)=>Object.fromEntries(Object.entries(current).map(([key,items])=>[key,applySession(items,targets.get(key).parentID,mutation)])))
|
|
2880
2933
|
}
|
|
2881
2934
|
function recordStatus(input){const mutation={...input,at:now(),startedAt:source?.startedAt?.(input.sessionID),observed:new Set
|
|
2882
2935
|
}
|
|
2883
2936
|
for(const journal of journals)
|
|
2884
2937
|
journal.statuses.push(mutation)
|
|
2885
|
-
|
|
2938
|
+
batch2(()=>{for(const [key,items] of Object.entries(snapshots())){if(items.every((item)=>item.id!==mutation.sessionID))
|
|
2886
2939
|
continue
|
|
2887
2940
|
history.observeStatus(key,mutation.sessionID,mutation.status,mutation.at,mutation.startedAt)
|
|
2888
2941
|
mutation.observed.add(key)
|
|
2889
2942
|
}
|
|
2890
|
-
if(
|
|
2943
|
+
if(options.cache==="model")
|
|
2891
2944
|
setStatuses((current)=>Object.fromEntries(Object.entries(current).map(([key,value])=>[key,applyStatus(value,mutation)])))
|
|
2892
2945
|
})
|
|
2893
2946
|
}
|
|
@@ -2913,14 +2966,13 @@ if(!requestState){journals.delete(journal)
|
|
|
2913
2966
|
return pending
|
|
2914
2967
|
}
|
|
2915
2968
|
const signal=AbortSignal.any([requestState.signal,AbortSignal.timeout(5000)])
|
|
2916
|
-
const request=
|
|
2917
|
-
}]):Promise.all([api.client.session.children({sessionID:current.parentID,...current.routing},{throwOnError:true,signal}),api.client.session.status(current.routing,{throwOnError:true,signal})])).then(async ([childResult,statusResult])=>{let nextChildren=childResult.data??[]
|
|
2969
|
+
const request=options.snapshot(current,signal).then(async (snapshot)=>{let nextChildren=snapshot.sessions
|
|
2918
2970
|
for(const mutation of journal.sessions)
|
|
2919
2971
|
nextChildren=applySession(nextChildren,current.parentID,mutation)
|
|
2920
|
-
let nextStatuses={...
|
|
2972
|
+
let nextStatuses={...snapshot.statuses}
|
|
2921
2973
|
const missing={}
|
|
2922
|
-
const remoteStatuses=
|
|
2923
|
-
return(remoteRetryAt.get(key)??0)<=now()?
|
|
2974
|
+
const remoteStatuses=options.remoteStatus?await Promise.all(nextChildren.map(async (session)=>{const key=JSON.stringify([current.key,session.id])
|
|
2975
|
+
return(remoteRetryAt.get(key)??0)<=now()?options.remoteStatus(session,requestState.signal):{sessionID:session.id,failed:true,cooldown:true,status:undefined}})):[]
|
|
2924
2976
|
if(!requestState.isCurrent())
|
|
2925
2977
|
return
|
|
2926
2978
|
for(const result of remoteStatuses){if(!result)
|
|
@@ -2946,7 +2998,7 @@ for(const mutation of journal.sessions)
|
|
|
2946
2998
|
nextChildren=applySession(nextChildren,current.parentID,mutation)
|
|
2947
2999
|
for(const mutation of journal.statuses)
|
|
2948
3000
|
nextStatuses=applyStatus(nextStatuses,mutation)
|
|
2949
|
-
if(requestState.isCurrent()){
|
|
3001
|
+
if(requestState.isCurrent()){batch2(()=>{for(const session of nextChildren){const mutations=journal.statuses.filter((mutation)=>mutation.sessionID===session.id)
|
|
2950
3002
|
if(mutations.length>0){for(const mutation of mutations){if(!mutation.observed.has(current.key))
|
|
2951
3003
|
history.observeStatus(current.key,session.id,mutation.status,mutation.at,mutation.startedAt)
|
|
2952
3004
|
}} else if(!missing[session.id]){const status=nextStatuses[session.id]??{type:"idle"}
|
|
@@ -2956,7 +3008,7 @@ history.observeStatus(current.key,session.id,status,now(),source?.startedAt?.(se
|
|
|
2956
3008
|
for(const mutation of journal.errors){if(mutation.sessionID===session.id&&!mutation.observed.has(current.key))
|
|
2957
3009
|
history.observeError(current.key,session.id,mutation.error,mutation.at)
|
|
2958
3010
|
}}
|
|
2959
|
-
if(
|
|
3011
|
+
if(options.cache==="model"){setChildren((value)=>({...value,[current.key]:nextChildren}))
|
|
2960
3012
|
setStatuses((value)=>({...value,[current.key]:nextStatuses}))
|
|
2961
3013
|
}
|
|
2962
3014
|
setUnavailable((value)=>({...value,[current.key]:missing}))
|
|
@@ -2976,8 +3028,8 @@ return request
|
|
|
2976
3028
|
function refresh(parentID,force=false){return refreshTarget(target(parentID),force)
|
|
2977
3029
|
}
|
|
2978
3030
|
function list(parentID){const current=target(parentID)
|
|
2979
|
-
const currentStatuses=source?Object.fromEntries(source.list(parentID).map((item)=>[item.id,source.status(item.id)])):statuses()[current.key]??{}
|
|
2980
|
-
return(snapshots()[current.key]??[]).map((session)=>({session,status:currentStatuses[session.id]??(unavailable()[current.key]?.[session.id]?undefined:
|
|
3031
|
+
const currentStatuses=options.cache==="source"?Object.fromEntries(source.list(parentID).map((item)=>[item.id,source.status(item.id)])):statuses()[current.key]??{}
|
|
3032
|
+
return(snapshots()[current.key]??[]).map((session)=>({session,status:currentStatuses[session.id]??(unavailable()[current.key]?.[session.id]?undefined:source.status(session.id))
|
|
2981
3033
|
})).filter((item)=>activeStatus(item.status)).map((item)=>({...item,run:history.active(current.key,item.session.id),unavailable:unavailable()[current.key]?.[item.session.id]
|
|
2982
3034
|
}))
|
|
2983
3035
|
}
|
|
@@ -2987,14 +3039,25 @@ return history.recent(current.key).flatMap((run)=>{const session=sessions.get(ru
|
|
|
2987
3039
|
return session?[{session,status:{type:"idle"},run,unavailable:false}]:[]
|
|
2988
3040
|
})
|
|
2989
3041
|
}
|
|
2990
|
-
const unsubscribe=
|
|
2991
|
-
|
|
2992
|
-
}
|
|
3042
|
+
const unsubscribe=options.subscribe((event)=>{switch(event.type){case "upsert":{recordSession(event)
|
|
3043
|
+
break
|
|
3044
|
+
}
|
|
3045
|
+
case "remove":{recordSession(event)
|
|
3046
|
+
recordStatus({sessionID:event.sessionID,status:{type:"idle"}})
|
|
3047
|
+
break
|
|
3048
|
+
}
|
|
3049
|
+
case "status":{recordStatus(event)
|
|
3050
|
+
break
|
|
3051
|
+
}
|
|
3052
|
+
case "error":{recordError(event)
|
|
3053
|
+
break
|
|
3054
|
+
}
|
|
3055
|
+
case "reconnect":{const current=activeTarget?targets.get(activeTarget):undefined
|
|
2993
3056
|
if(current)
|
|
2994
|
-
retryBackgroundRefresh(()=>refreshTarget(current),{signal:
|
|
2995
|
-
|
|
2996
|
-
|
|
2997
|
-
|
|
3057
|
+
retryBackgroundRefresh(()=>refreshTarget(current),{signal:options.lifecycle.signal}).catch(()=>{})
|
|
3058
|
+
break
|
|
3059
|
+
}}})
|
|
3060
|
+
options.lifecycle.onDispose(()=>{unsubscribe()
|
|
2998
3061
|
if(pollTimer)
|
|
2999
3062
|
clearTimeout(pollTimer)
|
|
3000
3063
|
})
|
|
@@ -3007,15 +3070,18 @@ clearTimeout(pollTimer)
|
|
|
3007
3070
|
requests.abortAll()
|
|
3008
3071
|
refreshing.clear()
|
|
3009
3072
|
activeTarget=current.key
|
|
3010
|
-
|
|
3073
|
+
leases=new Set
|
|
3074
|
+
const poll=()=>{if(activeTarget!==current.key||options.lifecycle.signal.aborted)
|
|
3011
3075
|
return
|
|
3012
3076
|
refreshTarget(current).catch(()=>{})
|
|
3013
3077
|
pollTimer=setTimeout(poll,POLL_INTERVAL_MS)
|
|
3014
3078
|
}
|
|
3015
|
-
if(
|
|
3079
|
+
if(options.cache==="model")
|
|
3016
3080
|
pollTimer=setTimeout(poll,POLL_INTERVAL_MS)
|
|
3017
3081
|
}
|
|
3018
|
-
|
|
3082
|
+
const lease=Symbol(current.key)
|
|
3083
|
+
leases.add(lease)
|
|
3084
|
+
return()=>{if(activeTarget!==current.key||!leases.delete(lease)||leases.size>0)
|
|
3019
3085
|
return
|
|
3020
3086
|
activeTarget=undefined
|
|
3021
3087
|
if(pollTimer)
|
|
@@ -3023,7 +3089,7 @@ clearTimeout(pollTimer)
|
|
|
3023
3089
|
pollTimer=undefined
|
|
3024
3090
|
requests.abortAll()
|
|
3025
3091
|
refreshing.clear()
|
|
3026
|
-
}},open(sessionID){
|
|
3092
|
+
}},open(sessionID){options.open(sessionID)
|
|
3027
3093
|
}}}
|
|
3028
3094
|
async function fetchDevTeamStatus(session,signal){const metadata=session.metadata
|
|
3029
3095
|
const devTeam=metadata&&typeof metadata.devTeam==="object"?metadata.devTeam:undefined
|
|
@@ -3044,10 +3110,26 @@ return{sessionID:session.id,failed:true}
|
|
|
3044
3110
|
const status=statuses[session.id]
|
|
3045
3111
|
if(status!==undefined&&(!status||typeof status!=="object"||!("type" in status)||!["idle","busy","retry"].includes(String(status.type))))
|
|
3046
3112
|
return{sessionID:session.id,failed:true}
|
|
3047
|
-
if(status&&typeof status==="object"&&"type" in status&&status.type==="retry"&&(!("next" in status)||typeof status.next!=="number"||!Number.isFinite(status.next)||!("attempt" in status)||typeof status.attempt!=="number"||!("message" in status)||typeof status.message!=="string"))
|
|
3113
|
+
if(status&&typeof status==="object"&&"type" in status&&status.type==="retry"&&(!("next" in status)||typeof status.next!=="number"||!Number.isFinite(status.next)||!("attempt" in status)||typeof status.attempt!=="number"||!("message" in status)||typeof status.message!=="string"))
|
|
3114
|
+
return{sessionID:session.id,failed:true}
|
|
3048
3115
|
return{sessionID:session.id,status}} catch{if(signal.aborted)
|
|
3049
3116
|
return
|
|
3050
3117
|
return{sessionID:session.id,failed:true}}}
|
|
3118
|
+
function createSubagentController(api,options={}){const source=options.source
|
|
3119
|
+
return createSubagentModel({now:options.now,lifecycle:api.lifecycle,cache:source?"source":"model",source:source??{list:()=>[],status:(id)=>api.state.session.status(id)??{type:"idle"},refresh:async ()=>{}},target(parentID){const parent=api.state.session.get(parentID)
|
|
3120
|
+
const directory=parent?.directory??api.state.path.directory
|
|
3121
|
+
const workspace=parent?.workspaceID
|
|
3122
|
+
return{key:JSON.stringify([parentID,directory,workspace??null]),parentID,routing:{directory,...workspace&&{workspace}}}},async snapshot(target,signal){if(source){await source.refresh(target.parentID,signal)
|
|
3123
|
+
const sessions=source.list(target.parentID)
|
|
3124
|
+
return{sessions,statuses:Object.fromEntries(sessions.map((session)=>[session.id,source.status(session.id)]))
|
|
3125
|
+
}}
|
|
3126
|
+
const [children,statuses]=await Promise.all([api.client.session.children({sessionID:target.parentID,...target.routing},{throwOnError:true,signal}),api.client.session.status(target.routing,{throwOnError:true,signal})])
|
|
3127
|
+
return{sessions:children.data??[],statuses:statuses.data??{}}},remoteStatus:source?undefined:fetchDevTeamStatus,subscribe(listener){const unsubscribe=[api.event.on("session.created",(event)=>listener({type:"upsert",info:event.properties.info})),api.event.on("session.updated",(event)=>listener({type:"upsert",info:event.properties.info})),api.event.on("session.deleted",(event)=>listener({type:"remove",sessionID:event.properties.sessionID})),api.event.on("session.status",(event)=>listener({type:"status",...event.properties})),api.event.on("session.error",(event)=>listener({type:"error",...event.properties})),api.event.on("session.idle",(event)=>listener({type:"status",sessionID:event.properties.sessionID,status:{type:"idle"}})),api.event.on("server.connected",()=>listener({type:"reconnect"}))]
|
|
3128
|
+
return()=>{for(const dispose of unsubscribe)
|
|
3129
|
+
dispose()
|
|
3130
|
+
}},open:(sessionID)=>api.route.navigate("session",{sessionID})
|
|
3131
|
+
})
|
|
3132
|
+
}
|
|
3051
3133
|
|
|
3052
3134
|
function filterSubagentView(rows,mode,query){const needle=query.trim().toLocaleLowerCase()
|
|
3053
3135
|
return rows.filter((row)=>{if(mode==="active"&&row.group!=="Active")
|
|
@@ -3085,30 +3167,32 @@ onCleanup6(()=>clearInterval(timer))
|
|
|
3085
3167
|
return now
|
|
3086
3168
|
}
|
|
3087
3169
|
|
|
3088
|
-
function
|
|
3170
|
+
function createTodoModel(options){const [sessions,setSessions]=createSignal10({})
|
|
3089
3171
|
const refreshing=new Map
|
|
3090
3172
|
const revisions=new Map
|
|
3091
|
-
const requests=createRequestState(
|
|
3173
|
+
const requests=createRequestState(options.lifecycle.signal)
|
|
3092
3174
|
let activeTarget
|
|
3093
|
-
|
|
3094
|
-
|
|
3095
|
-
|
|
3096
|
-
return{key:JSON.stringify([sessionID,directory,workspace??null]),sessionID,routing:{directory,...workspace&&{workspace}}}}
|
|
3175
|
+
let leases=new Set
|
|
3176
|
+
function target(sessionID){return options.target(sessionID)
|
|
3177
|
+
}
|
|
3097
3178
|
function set(current,todos){setSessions((value)=>({...value,[current.key]:todos}))
|
|
3098
3179
|
}
|
|
3099
3180
|
function list(sessionID){const current=target(sessionID)
|
|
3100
|
-
return sessions()[current.key]??
|
|
3181
|
+
return options.cache==="source"?options.source.list(sessionID):sessions()[current.key]??options.source.list(sessionID)
|
|
3101
3182
|
}
|
|
3102
|
-
|
|
3183
|
+
function refresh(sessionID,force=false){if(options.lifecycle.signal.aborted)
|
|
3184
|
+
return Promise.resolve([])
|
|
3185
|
+
const current=target(sessionID)
|
|
3103
3186
|
const pending=refreshing.get(current.key)
|
|
3104
3187
|
if(pending&&!force)
|
|
3105
3188
|
return pending
|
|
3106
|
-
const revision=revisions.get(
|
|
3107
|
-
const requestState=requests.start(current.key,"refresh todos",current.key in sessions(),force)
|
|
3189
|
+
const revision=revisions.get(current.key)??0
|
|
3190
|
+
const requestState=requests.start(current.key,"refresh todos",current.key in sessions()||Boolean(options.hasValue?.(sessionID)),force)
|
|
3108
3191
|
if(!requestState)
|
|
3109
3192
|
return pending
|
|
3110
|
-
const request=
|
|
3111
|
-
|
|
3193
|
+
const request=Promise.try(()=>options.source.refresh(sessionID,requestState.signal)).then((todos)=>{if(!requestState.isCurrent())
|
|
3194
|
+
return []
|
|
3195
|
+
if(options.cache==="model"&&(revisions.get(current.key)??0)===revision)
|
|
3112
3196
|
set(current,todos)
|
|
3113
3197
|
requestState.succeed()
|
|
3114
3198
|
return todos
|
|
@@ -3121,24 +3205,37 @@ refreshing.delete(current.key)
|
|
|
3121
3205
|
refreshing.set(current.key,request)
|
|
3122
3206
|
return request
|
|
3123
3207
|
}
|
|
3124
|
-
const unsubscribe=
|
|
3125
|
-
revisions.set(
|
|
3126
|
-
set(
|
|
3208
|
+
const unsubscribe=options.source.subscribe?.((sessionID,todos)=>{const current=target(sessionID)
|
|
3209
|
+
revisions.set(current.key,(revisions.get(current.key)??0) + 1)
|
|
3210
|
+
set(current,todos)
|
|
3127
3211
|
})
|
|
3128
|
-
|
|
3212
|
+
if(unsubscribe)
|
|
3213
|
+
options.lifecycle.onDispose(unsubscribe)
|
|
3129
3214
|
return{target,list,refresh,state(sessionID){return requests.state(target(sessionID).key)
|
|
3130
3215
|
},retry(sessionID){return refresh(sessionID,true)
|
|
3131
3216
|
},activate(sessionID){const key=target(sessionID).key
|
|
3132
3217
|
if(activeTarget!==key){requests.abortAll()
|
|
3133
3218
|
refreshing.clear()
|
|
3134
3219
|
activeTarget=key
|
|
3220
|
+
leases=new Set
|
|
3135
3221
|
}
|
|
3136
|
-
|
|
3222
|
+
const lease=Symbol(key)
|
|
3223
|
+
leases.add(lease)
|
|
3224
|
+
return()=>{if(activeTarget!==key||!leases.delete(lease)||leases.size>0)
|
|
3137
3225
|
return
|
|
3138
3226
|
activeTarget=undefined
|
|
3139
3227
|
requests.abortAll()
|
|
3140
3228
|
refreshing.clear()
|
|
3141
3229
|
}}}}
|
|
3230
|
+
function createTodoController(api){const target=(sessionID)=>{const session=api.state.session.get(sessionID)
|
|
3231
|
+
const directory=session?.directory??api.state.path.directory
|
|
3232
|
+
const workspace=session?.workspaceID
|
|
3233
|
+
return{key:JSON.stringify([sessionID,directory,workspace??null]),sessionID,routing:{directory,...workspace&&{workspace}}}}
|
|
3234
|
+
return createTodoModel({lifecycle:api.lifecycle,target,cache:"model",source:{list:(sessionID)=>api.state.session.todo(sessionID),async refresh(sessionID,signal){const result=await api.client.session.todo({sessionID,...target(sessionID).routing},{throwOnError:true,signal})
|
|
3235
|
+
return result.data??[]
|
|
3236
|
+
},subscribe:(listener)=>api.event.on("todo.updated",(event)=>listener(event.properties.sessionID,event.properties.todos))
|
|
3237
|
+
}})
|
|
3238
|
+
}
|
|
3142
3239
|
|
|
3143
3240
|
function buildTodoView(todos,mode){const active=[...todos.filter((item)=>item.status==="in_progress"),...todos.filter((item)=>item.status==="pending")]
|
|
3144
3241
|
const completed=todos.filter((item)=>item.status==="completed")
|
|
@@ -3176,91 +3273,24 @@ function openKeyboardHelp(api,iconStyle=()=>"nerd",multilineCorners=()=>true,sho
|
|
|
3176
3273
|
|
|
3177
3274
|
|
|
3178
3275
|
|
|
3179
|
-
|
|
3180
|
-
var defaults={todo:true,lsp:true}
|
|
3181
|
-
var capabilities=new WeakMap
|
|
3182
|
-
function setHostCapabilities(api,value){capabilities.set(api,value)
|
|
3183
|
-
}
|
|
3184
|
-
function hostCapabilities(api){return capabilities.get(api)??defaults
|
|
3185
|
-
}
|
|
3186
|
-
function hostCapabilityUnavailable(api,section){return section==="todo"||section==="lsp"?hostCapabilities(api).unavailable?.[section]:undefined
|
|
3187
|
-
}
|
|
3188
|
-
function supportsSidebarSection(api,section){const current=hostCapabilities(api)
|
|
3189
|
-
return section!=="todo"&§ion!=="lsp"?true:current[section]
|
|
3190
|
-
}
|
|
3191
|
-
function supportsTitleVisibility(api){return hostCapabilities(api).titleVisibility!==false
|
|
3192
|
-
}
|
|
3193
|
-
function supportsPermissionMode(api){return hostCapabilities(api).permissionMode!==false
|
|
3194
|
-
}
|
|
3195
3276
|
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"]]
|
|
3196
3277
|
var QUICK_ACTIONS=QUICK_ACTION_IDS.map((command,index)=>({command,icon:QUICK_ACTION_METADATA[index][0],label:QUICK_ACTION_METADATA[index][1]
|
|
3197
3278
|
}))
|
|
3198
3279
|
function quickActionRequiresSession(command){return command!=="session.list"&&command!=="session.new"&&command!=="permission.mode"
|
|
3199
3280
|
}
|
|
3200
|
-
function quickActionLabel(api,action){if(action.command!=="permission.mode")
|
|
3201
|
-
return action.label
|
|
3202
|
-
const command=api.keymap.getCommands?.({visibility:"registered"}).find((candidate)=>candidate.name===action.command)
|
|
3203
|
-
return typeof command?.title==="string"?command.title:action.label
|
|
3204
|
-
}
|
|
3205
|
-
function createQuickActionRevision(api){const [revision,setRevision]=createSignal12(0)
|
|
3206
|
-
const unsubscribe=api.keymap.on?.("state",()=>setRevision((value)=>value + 1))
|
|
3207
|
-
if(unsubscribe)
|
|
3208
|
-
onCleanup8(unsubscribe)
|
|
3209
|
-
return revision
|
|
3210
|
-
}
|
|
3211
3281
|
function orderQuickActionIds(order,favorites){return [...order.filter((id)=>favorites.has(id)),...order.filter((id)=>!favorites.has(id))]
|
|
3212
3282
|
}
|
|
3213
|
-
function quickActionDisabledReason(api,action){const route=api.route.current
|
|
3214
|
-
if(quickActionRequiresSession(action.command)&&route.name!=="session")
|
|
3215
|
-
return "Requires an open session"
|
|
3216
|
-
const getCommands=api.keymap.getCommands?.bind(api.keymap)
|
|
3217
|
-
if(!getCommands)
|
|
3218
|
-
return
|
|
3219
|
-
const command=getCommands({visibility:"registered"}).find((candidate)=>candidate.name===action.command)
|
|
3220
|
-
if(!command)
|
|
3221
|
-
return hostCapabilities(api).commandsReachableOnly?"Unavailable in the current session":"Unavailable in this OpenCode version"
|
|
3222
|
-
const enabled=command.enabled
|
|
3223
|
-
if(enabled===false||typeof enabled==="function"&&!enabled())
|
|
3224
|
-
return "Unavailable in the current session"
|
|
3225
|
-
return
|
|
3226
|
-
}
|
|
3227
|
-
var sources=new WeakMap
|
|
3228
|
-
function setQuickActionStateSource(api,source){sources.set(api,source)
|
|
3229
|
-
}
|
|
3230
|
-
function currentPermissionMode(api){const title=api.keymap.getCommands?.({visibility:"registered"}).find((command)=>command.name==="permission.mode")?.title
|
|
3231
|
-
if(typeof title!=="string")
|
|
3232
|
-
return
|
|
3233
|
-
if(title.startsWith("Disable auto-approve permissions"))
|
|
3234
|
-
return true
|
|
3235
|
-
return title.startsWith("Enable auto-approve permissions")?false:undefined
|
|
3236
|
-
}
|
|
3237
|
-
function quickActionStates(api,id){if(id==="permission.mode"&¤tPermissionMode(api)!==undefined)
|
|
3238
|
-
return [{id:"on",label:"Auto-approve on"},{id:"off",label:"Auto-approve off"}]
|
|
3239
|
-
if(id==="session.compact"&&sources.has(api))
|
|
3240
|
-
return [{id:"idle",label:"Idle"},{id:"compacting",label:"Compacting"}]
|
|
3241
|
-
return []
|
|
3242
|
-
}
|
|
3243
|
-
function quickActionState(api,id){if(id==="permission.mode"){const mode=currentPermissionMode(api)
|
|
3244
|
-
if(mode===undefined)
|
|
3245
|
-
return
|
|
3246
|
-
return mode?"on":"off"
|
|
3247
|
-
}
|
|
3248
|
-
return sources.get(api)?.(id)
|
|
3249
|
-
}
|
|
3250
3283
|
var SEARCH_GROUPS=["Skills","Subagents","MCP","Actions"]
|
|
3251
3284
|
var SEARCH_SECTIONS={Skills:"skills",Subagents:"subagents",MCP:"mcp",Actions:"quick_actions"
|
|
3252
3285
|
}
|
|
3253
|
-
function searchContext(api){const route=api.route.current
|
|
3254
|
-
const sessionID=route.name==="session"&&"params" in route&&typeof route.params?.sessionID==="string"?route.params.sessionID:undefined
|
|
3255
|
-
const location=currentLocation(api)
|
|
3256
|
-
return{sessionID,location,key:JSON.stringify([route.name,sessionID??null,location.key])}}
|
|
3257
3286
|
function buildSearchCandidates(input){const recent=new Map(input.recentSkills.map((location,index)=>[location,index]))
|
|
3258
3287
|
const skills=[...input.skills].sort((a,b)=>Number(input.favoriteSkills.has(b.location))-Number(input.favoriteSkills.has(a.location))||(recent.get(a.location)??Infinity)-(recent.get(b.location)??Infinity)||a.name.localeCompare(b.name))
|
|
3259
3288
|
const mcp=[...input.mcp].sort((a,b)=>Number(input.favoriteMcp.has(b.name))-Number(input.favoriteMcp.has(a.name))||a.name.localeCompare(b.name))
|
|
3260
3289
|
const results=[...skills.map((skill)=>({id:`skill:${skill.location || skill.name}`,group:"Skills",title:skill.name,description:[input.skillGroups?.[skill.location],skill.description?.trim()||skill.location].filter(Boolean).join(" \xB7 "),keywords:`${skill.location} ${input.skillGroups?.[skill.location] ?? ""}`,skill
|
|
3261
3290
|
})),...input.subagents.map((item)=>({id:`subagent:${item.session.id}`,group:"Subagents",title:item.session.title,description:[item.run?.outcome??item.status.type,item.run?.errorMessage].filter(Boolean).join(" \xB7 "),keywords:item.session.id,sessionID:item.session.id
|
|
3262
|
-
})),...mcp.map((item)=>({id:`mcp:${item.name}`,group:"MCP",title:item.name,description:[input.mcpGroups?.[item.name],mcpToggleAction2(item.status)==="disconnect"?"Disconnect":"Connect",item.status,item.error].filter(Boolean).join(" \xB7 "),keywords:input.mcpGroups?.[item.name],disabled:input.mcpBusy||!mcpToggleAction2(item.status)?"MCP operation in progress":undefined,server:item.name
|
|
3263
|
-
|
|
3291
|
+
})),...mcp.map((item)=>({id:`mcp:${item.name}`,group:"MCP",title:item.name,description:[input.mcpGroups?.[item.name],mcpToggleAction2(item.status)==="disconnect"?"Disconnect":"Connect",item.status,input.mcpErrorMode==="details"?undefined:item.error].filter(Boolean).join(" \xB7 "),keywords:input.mcpGroups?.[item.name],disabled:input.mcpBusy||!mcpToggleAction2(item.status)?"MCP operation in progress":undefined,server:item.name,...input.mcpErrorMode==="details"&&item.error&&{information:{title:`MCP \xB7 ${item.name}`,body:`Status: ${item.status}
|
|
3292
|
+
|
|
3293
|
+
${item.error}`}}})),...orderQuickActionIds(input.actionOrder,input.favoriteQuickActions??new Set).flatMap((id)=>{const action=QUICK_ACTIONS.find((item)=>item.command===id)
|
|
3264
3294
|
return action?[{id:`action:${id}`,group:"Actions",title:input.actionLabel?.(action)??action.label,description:id,command:id,disabled:input.actionDisabledReason?.(action)??(quickActionRequiresSession(action.command)&&!input.hasSession?"Requires an open session":undefined)
|
|
3265
3295
|
}]:[]
|
|
3266
3296
|
})]
|
|
@@ -3297,6 +3327,11 @@ return [{item,score,index}]
|
|
|
3297
3327
|
scored.sort((a,b)=>SEARCH_GROUPS.indexOf(a.item.group)-SEARCH_GROUPS.indexOf(b.item.group)||b.score-a.score||a.index-b.index)
|
|
3298
3328
|
return scored.map(({item})=>item)
|
|
3299
3329
|
}
|
|
3330
|
+
function searchContext(api){const route=api.route.current
|
|
3331
|
+
const sessionID=route.name==="session"&&"params" in route&&typeof route.params?.sessionID==="string"?route.params.sessionID:undefined
|
|
3332
|
+
const location=currentLocation(api)
|
|
3333
|
+
return{sessionID,location,key:JSON.stringify([route.name,sessionID??null,location.key])}}
|
|
3334
|
+
|
|
3300
3335
|
|
|
3301
3336
|
|
|
3302
3337
|
|
|
@@ -3310,6 +3345,69 @@ return scored.map(({item})=>item)
|
|
|
3310
3345
|
|
|
3311
3346
|
|
|
3312
3347
|
|
|
3348
|
+
var defaults={todo:true,lsp:true}
|
|
3349
|
+
var capabilities=new WeakMap
|
|
3350
|
+
function setHostCapabilities(api,value){capabilities.set(api,value)
|
|
3351
|
+
}
|
|
3352
|
+
function hostCapabilities(api){return capabilities.get(api)??defaults
|
|
3353
|
+
}
|
|
3354
|
+
function hostCapabilityUnavailable(api,section){return section==="todo"||section==="lsp"?hostCapabilities(api).unavailable?.[section]:undefined
|
|
3355
|
+
}
|
|
3356
|
+
function supportsSidebarSection(api,section){const current=hostCapabilities(api)
|
|
3357
|
+
return section!=="todo"&§ion!=="lsp"?true:current[section]
|
|
3358
|
+
}
|
|
3359
|
+
function supportsTitleVisibility(api){return hostCapabilities(api).titleVisibility!==false
|
|
3360
|
+
}
|
|
3361
|
+
function supportsPermissionMode(api){return hostCapabilities(api).permissionMode!==false
|
|
3362
|
+
}
|
|
3363
|
+
function quickActionLabel(api,action){if(action.command!=="permission.mode")
|
|
3364
|
+
return action.label
|
|
3365
|
+
const command=api.keymap.getCommands?.({visibility:"registered"}).find((candidate)=>candidate.name===action.command)
|
|
3366
|
+
return typeof command?.title==="string"?command.title:action.label
|
|
3367
|
+
}
|
|
3368
|
+
function createQuickActionRevision(api){const [revision,setRevision]=createSignal12(0)
|
|
3369
|
+
const unsubscribe=api.keymap.on?.("state",()=>setRevision((value)=>value + 1))
|
|
3370
|
+
if(unsubscribe)
|
|
3371
|
+
onCleanup8(unsubscribe)
|
|
3372
|
+
return revision
|
|
3373
|
+
}
|
|
3374
|
+
function quickActionDisabledReason(api,action){const route=api.route.current
|
|
3375
|
+
if(quickActionRequiresSession(action.command)&&route.name!=="session")
|
|
3376
|
+
return "Requires an open session"
|
|
3377
|
+
const getCommands=api.keymap.getCommands?.bind(api.keymap)
|
|
3378
|
+
if(!getCommands)
|
|
3379
|
+
return
|
|
3380
|
+
const command=getCommands({visibility:"registered"}).find((candidate)=>candidate.name===action.command)
|
|
3381
|
+
if(!command)
|
|
3382
|
+
return hostCapabilities(api).commandsReachableOnly?"Unavailable in the current session":"Unavailable in this OpenCode version"
|
|
3383
|
+
const enabled=command.enabled
|
|
3384
|
+
if(enabled===false||typeof enabled==="function"&&!enabled())
|
|
3385
|
+
return "Unavailable in the current session"
|
|
3386
|
+
return
|
|
3387
|
+
}
|
|
3388
|
+
var sources=new WeakMap
|
|
3389
|
+
function setQuickActionStateSource(api,source){sources.set(api,source)
|
|
3390
|
+
}
|
|
3391
|
+
function currentPermissionMode(api){const title=api.keymap.getCommands?.({visibility:"registered"}).find((command)=>command.name==="permission.mode")?.title
|
|
3392
|
+
if(typeof title!=="string")
|
|
3393
|
+
return
|
|
3394
|
+
if(title.startsWith("Disable auto-approve permissions"))
|
|
3395
|
+
return true
|
|
3396
|
+
return title.startsWith("Enable auto-approve permissions")?false:undefined
|
|
3397
|
+
}
|
|
3398
|
+
function quickActionStates(api,id){if(id==="permission.mode"&¤tPermissionMode(api)!==undefined)
|
|
3399
|
+
return [{id:"on",label:"Auto-approve on"},{id:"off",label:"Auto-approve off"}]
|
|
3400
|
+
if(id==="session.compact"&&sources.has(api))
|
|
3401
|
+
return [{id:"idle",label:"Idle"},{id:"compacting",label:"Compacting"}]
|
|
3402
|
+
return []
|
|
3403
|
+
}
|
|
3404
|
+
function quickActionState(api,id){if(id==="permission.mode"){const mode=currentPermissionMode(api)
|
|
3405
|
+
if(mode===undefined)
|
|
3406
|
+
return
|
|
3407
|
+
return mode?"on":"off"
|
|
3408
|
+
}
|
|
3409
|
+
return sources.get(api)?.(id)
|
|
3410
|
+
}
|
|
3313
3411
|
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)
|
|
3314
3412
|
}
|
|
3315
3413
|
function createSearchDialogController(props){const context=searchContext(props.api)
|
|
@@ -3395,7 +3493,7 @@ function selectTab(tab){if(tab!==activeTab()){tabViews.set(activeTab(),{selected
|
|
|
3395
3493
|
})
|
|
3396
3494
|
const saved=tabViews.get(tab)
|
|
3397
3495
|
pendingScroll=saved?.scrollTop??0
|
|
3398
|
-
|
|
3496
|
+
batch3(()=>{setActiveTab(tab)
|
|
3399
3497
|
setSelectedID(saved?.selectedID)
|
|
3400
3498
|
})
|
|
3401
3499
|
}
|
|
@@ -3700,14 +3798,17 @@ clearTimeout(timer)
|
|
|
3700
3798
|
return _$createElement("box")
|
|
3701
3799
|
}
|
|
3702
3800
|
|
|
3703
|
-
|
|
3801
|
+
var alwaysCurrent=()=>true
|
|
3802
|
+
function createMcpPresetPreview(controller,preferences,name,isCurrent=alwaysCurrent){const target=controller.target()
|
|
3704
3803
|
const valid=()=>{const current=controller.target()
|
|
3705
|
-
return current.key===target.key&¤t.scope===target.scope
|
|
3804
|
+
return isCurrent()&¤t.key===target.key&¤t.scope===target.scope
|
|
3706
3805
|
}
|
|
3707
3806
|
const preset=createMemo2(()=>preferences.mcpPresets()[name])
|
|
3708
|
-
const preview=createMemo2(()=>mcpPresetPreview(controller.list(target),preset()??{}))
|
|
3807
|
+
const preview=createMemo2(()=>mcpPresetPreview(valid()?controller.list(target):[],preset()??{}))
|
|
3709
3808
|
const state=createMemo2(()=>controller.state(target))
|
|
3710
|
-
const blocked=createMemo2(()=>{if(!
|
|
3809
|
+
const blocked=createMemo2(()=>{if(!valid())
|
|
3810
|
+
return "Session or server changed; reopen the preview."
|
|
3811
|
+
if(!preset())
|
|
3711
3812
|
return "Preset no longer exists."
|
|
3712
3813
|
if(controller.mutating(target))
|
|
3713
3814
|
return "Wait for the current MCP operation to finish."
|
|
@@ -5629,6 +5730,9 @@ return _$createComponent(SectionWithHeaderAction,{get api(){return props.api
|
|
|
5629
5730
|
|
|
5630
5731
|
|
|
5631
5732
|
|
|
5733
|
+
var CHATGPT_METHODS=new Set(["chatgpt-browser","chatgpt-headless"]);
|
|
5734
|
+
|
|
5735
|
+
|
|
5632
5736
|
|
|
5633
5737
|
|
|
5634
5738
|
|
|
@@ -5686,6 +5790,35 @@ return _$createComponent(SectionWithHeaderAction,{get api(){return props.api
|
|
|
5686
5790
|
|
|
5687
5791
|
|
|
5688
5792
|
|
|
5793
|
+
var scheduleInterval=(callback,milliseconds)=>{const timer=setInterval(callback,milliseconds)
|
|
5794
|
+
return()=>clearInterval(timer)
|
|
5795
|
+
}
|
|
5796
|
+
function createLimitsRefresh(options,schedule=scheduleInterval){let disposed=false
|
|
5797
|
+
const selectedKey=createMemo12(()=>JSON.stringify(options.selectedModel?.()))
|
|
5798
|
+
const targetKey=createMemo12(()=>JSON.stringify(options.controller.current().model))
|
|
5799
|
+
const interval=createMemo12(()=>(parseLimitsRefreshMinutes(options.refreshMinutes?.())??DEFAULT_LIMITS_REFRESH_MINUTES)*60000)
|
|
5800
|
+
createEffect16(on2(selectedKey,()=>{const model=options.selectedModel?.()
|
|
5801
|
+
if(model&&options.accountSource)
|
|
5802
|
+
options.accountSource.refresh(model).catch(()=>{})
|
|
5803
|
+
}))
|
|
5804
|
+
createEffect16(on2(targetKey,()=>{const{model,adapter}=options.controller.current()
|
|
5805
|
+
if(model&&adapter)
|
|
5806
|
+
options.controller.refresh()
|
|
5807
|
+
}))
|
|
5808
|
+
async function refresh(){if(disposed)
|
|
5809
|
+
return
|
|
5810
|
+
const target=targetKey()
|
|
5811
|
+
const model=options.selectedModel?.()
|
|
5812
|
+
if(model&&options.accountSource)
|
|
5813
|
+
await options.accountSource.refresh(model)
|
|
5814
|
+
if(!disposed&&target===targetKey())
|
|
5815
|
+
await options.controller.refresh()
|
|
5816
|
+
}
|
|
5817
|
+
createEffect16(on2(interval,(milliseconds)=>{onCleanup20(schedule(()=>void refresh().catch(()=>{}),milliseconds))
|
|
5818
|
+
}))
|
|
5819
|
+
onCleanup20(()=>{disposed=true
|
|
5820
|
+
})
|
|
5821
|
+
}
|
|
5689
5822
|
|
|
5690
5823
|
|
|
5691
5824
|
|
|
@@ -5739,12 +5872,12 @@ function QuickActionRow(props){const{api,interaction
|
|
|
5739
5872
|
const icons=useIcons()
|
|
5740
5873
|
const toolbar=useToolbar()
|
|
5741
5874
|
const theme=()=>api.theme.current
|
|
5742
|
-
const [width,setWidth]=
|
|
5743
|
-
const shortcut=
|
|
5875
|
+
const [width,setWidth]=createSignal34(0)
|
|
5876
|
+
const shortcut=createMemo13(()=>{const bindings=api.keymap.getCommandBindings({visibility:"registered",commands:[props.action.command]
|
|
5744
5877
|
})
|
|
5745
5878
|
return api.keys.formatBindings(bindings.get(props.action.command))
|
|
5746
5879
|
})
|
|
5747
|
-
const visibleShortcut=
|
|
5880
|
+
const visibleShortcut=createMemo13(()=>{const value=shortcut()
|
|
5748
5881
|
return value&&width()>=Bun.stringWidth(props.action.label) + Bun.stringWidth(value) + (toolbar?11:8)?value:undefined
|
|
5749
5882
|
})
|
|
5750
5883
|
function run(){if(props.action.command==="session.new"&&props.onNewSession?.())
|
|
@@ -5808,7 +5941,7 @@ return _el$4
|
|
|
5808
5941
|
}})
|
|
5809
5942
|
}
|
|
5810
5943
|
function QuickActionsSection(props){const commandRevision=createQuickActionRevision(props.api)
|
|
5811
|
-
const actions=
|
|
5944
|
+
const actions=createMemo14(()=>{commandRevision()
|
|
5812
5945
|
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)
|
|
5813
5946
|
return action&&props.preferences.quickActionVisible?.(id)!==false?[{...action,label:quickActionLabel(props.api,action),disabled:quickActionDisabledReason(props.api,action)
|
|
5814
5947
|
}]:[]
|
|
@@ -5892,13 +6025,13 @@ item.activate(event)
|
|
|
5892
6025
|
|
|
5893
6026
|
|
|
5894
6027
|
function SidebarToggleBinding(props){const shortcuts=createSidebarShortcutMode(props.api)
|
|
5895
|
-
|
|
6028
|
+
createEffect17(()=>{const key=props.preferences.toggleKey()
|
|
5896
6029
|
untrack6(()=>shortcuts.bind(key))
|
|
5897
6030
|
})
|
|
5898
|
-
|
|
6031
|
+
createEffect17(()=>{if(shortcuts.active()&&(props.api.route.current.name!=="session"||props.api.ui.dialog.open||props.api.mode.current()==="modal"))
|
|
5899
6032
|
untrack6(shortcuts.cancel)
|
|
5900
6033
|
})
|
|
5901
|
-
|
|
6034
|
+
onCleanup21(shortcuts.dispose)
|
|
5902
6035
|
return(()=>{var _el$=_$createElement("box")
|
|
5903
6036
|
_$setProp(_el$,"position","absolute")
|
|
5904
6037
|
_$setProp(_el$,"top",0)
|
|
@@ -5920,11 +6053,11 @@ const unregisterCommands=props.api.keymap.registerLayer({commands:[...commands,.
|
|
|
5920
6053
|
})=>({name:name.replace(PLUGIN_ID,()=>LEGACY_PLUGIN_ID),run,enabled
|
|
5921
6054
|
}))]
|
|
5922
6055
|
})
|
|
5923
|
-
|
|
5924
|
-
|
|
6056
|
+
onCleanup21(unregisterCommands)
|
|
6057
|
+
createEffect17(()=>{const unregister=props.api.keymap.registerLayer({bindings:[{key:props.preferences.focusKey(),cmd:FOCUS_COMMAND
|
|
5925
6058
|
}]
|
|
5926
6059
|
})
|
|
5927
|
-
|
|
6060
|
+
onCleanup21(unregister)
|
|
5928
6061
|
})
|
|
5929
6062
|
return _$createElement("box")
|
|
5930
6063
|
}
|
|
@@ -5976,6 +6109,26 @@ rows.push(visible)
|
|
|
5976
6109
|
}
|
|
5977
6110
|
return{columns,overflow,rows,...widths&&{sizes}}}
|
|
5978
6111
|
|
|
6112
|
+
var PRIVATE_KEYS=new Set(["favoriteSkills","favoriteMcpServers","favoriteQuickActions","skillGroups","recentSkills","recentQuickActions","skippedSkillConfirmations","onboardingCompleted","codexAccountBindings","pendingResetAttempt","lastNavigatorVersion","previousNavigatorVersion","worktrees","user"]);
|
|
6113
|
+
function createPinnedToolbarModel(ports){function view(pin){const action=pin.kind==="action"?ports.action(pin.id):undefined
|
|
6114
|
+
const skill=pin.kind==="skill"?ports.skill(pin):undefined
|
|
6115
|
+
return{label:action?.label??(pin.kind==="skill"?pin.name:pin.id),stateLabel:action?.stateLabel,icons:toolbarPinIcons(pin,action?.state),text:pin.text,reason:action?.reason??skill?.reason
|
|
6116
|
+
}}
|
|
6117
|
+
function run(key){const pin=ports.pins().find((item)=>toolbarPinKey(item)===key)
|
|
6118
|
+
if(!pin)
|
|
6119
|
+
return
|
|
6120
|
+
const item=view(pin)
|
|
6121
|
+
if(item.reason){ports.unavailable(item.label,item.reason)
|
|
6122
|
+
return
|
|
6123
|
+
}
|
|
6124
|
+
if(pin.kind==="action"){ports.runAction(pin.id)
|
|
6125
|
+
return
|
|
6126
|
+
}
|
|
6127
|
+
const skill=ports.skill(pin).skill
|
|
6128
|
+
if(skill)
|
|
6129
|
+
ports.runSkill(skill)
|
|
6130
|
+
}
|
|
6131
|
+
return{pins:ports.pins,view,run}}
|
|
5979
6132
|
function toolbarPinWidth(pin){const states=Object.keys({...pin.stateIcons,...pin.stateIconLists})
|
|
5980
6133
|
const count=Math.max(toolbarPinIcons(pin).length,...states.map((state)=>toolbarPinIcons(pin,state).length))
|
|
5981
6134
|
const iconsWidth=Math.max(0,count*2-1)
|
|
@@ -5984,49 +6137,34 @@ return 2 + Math.max(1,iconsWidth + (count&&pin.text?1:0) + Bun.stringWidth(pin.t
|
|
|
5984
6137
|
function createToolbarModel(props){const icons=useIcons()
|
|
5985
6138
|
const revision=createQuickActionRevision(props.api)
|
|
5986
6139
|
const pins=()=>props.preferences.toolbarPins?.()??[]
|
|
5987
|
-
const needsSkills=
|
|
5988
|
-
const target=
|
|
5989
|
-
|
|
6140
|
+
const needsSkills=createMemo15(()=>pins().some((pin)=>pin.kind==="skill"))
|
|
6141
|
+
const target=createMemo15(()=>props.skills.target())
|
|
6142
|
+
createEffect18(()=>{if(!needsSkills())
|
|
5990
6143
|
return
|
|
5991
6144
|
const current=target()
|
|
5992
6145
|
const release=untrack7(()=>props.skills.activate(current))
|
|
5993
|
-
|
|
6146
|
+
onCleanup22(release)
|
|
5994
6147
|
untrack7(()=>{props.skills.refresh(current).catch(()=>{})
|
|
5995
6148
|
})
|
|
5996
6149
|
})
|
|
5997
|
-
|
|
5998
|
-
|
|
5999
|
-
const state=quickActionState(props.api,
|
|
6000
|
-
|
|
6001
|
-
|
|
6002
|
-
}}
|
|
6003
|
-
const skill=props.skills.list(target()).find((item)=>item.location===pin.location&&item.name===pin.name)
|
|
6150
|
+
const model=createPinnedToolbarModel({pins,action(id){revision()
|
|
6151
|
+
const action=QUICK_ACTIONS.find((item)=>item.command===id)
|
|
6152
|
+
const state=quickActionState(props.api,id)
|
|
6153
|
+
return{label:quickActionLabel(props.api,action),state,stateLabel:quickActionStates(props.api,id).find((item)=>item.id===state)?.label,reason:quickActionDisabledReason(props.api,action)
|
|
6154
|
+
}},skill(pin){const skill=props.skills.list(target()).find((item)=>item.location===pin.location&&item.name===pin.name)
|
|
6004
6155
|
const request=props.skills.state(target())
|
|
6005
6156
|
const unavailable=request.status==="loading"?"Loading Skills":"Skill is unavailable in this workspace"
|
|
6006
|
-
return{
|
|
6007
|
-
}}
|
|
6008
|
-
function run(key){const pin=pins().find((item)=>toolbarPinKey(item)===key)
|
|
6009
|
-
if(!pin)
|
|
6010
|
-
return
|
|
6011
|
-
const item=view(pin)
|
|
6012
|
-
if(item.reason){props.api.ui.toast({variant:"warning",title:item.label,message:item.reason})
|
|
6157
|
+
return{skill,reason:request.error?.message??(skill?skillUnavailable(props.skills,skill):unavailable)}},unavailable:(title,message)=>props.api.ui.toast({variant:"warning",title,message}),runAction(id){if(id==="session.new"&&props.onNewSession?.())
|
|
6013
6158
|
return
|
|
6014
|
-
|
|
6015
|
-
if(pin.kind==="action"){if(pin.id==="session.new"&&props.onNewSession?.())
|
|
6016
|
-
return
|
|
6017
|
-
const result=props.interaction.dispatchFromReturnTarget(pin.id)
|
|
6159
|
+
const result=props.interaction.dispatchFromReturnTarget(id)
|
|
6018
6160
|
if(!result.ok)
|
|
6019
|
-
props.api.ui.toast({variant:"warning",title:item.
|
|
6020
|
-
|
|
6021
|
-
}
|
|
6022
|
-
const skill=props.skills.list(target()).find((candidate)=>candidate.location===pin.location&&candidate.name===pin.name)
|
|
6023
|
-
if(!skill)
|
|
6024
|
-
return
|
|
6025
|
-
const route=JSON.stringify(props.api.route.current)
|
|
6161
|
+
props.api.ui.toast({variant:"warning",title:quickActionLabel(props.api,QUICK_ACTIONS.find((item)=>item.command===id)),message:`Command is ${result.reason}`
|
|
6162
|
+
})
|
|
6163
|
+
},runSkill(skill){const route=JSON.stringify(props.api.route.current)
|
|
6026
6164
|
const dialogs=createDialogStack(props.api,icons.style,()=>route===JSON.stringify(props.api.route.current),icons.multilineCorners)
|
|
6027
6165
|
activateSkill({api:props.api,controller:props.skills,access:props.preferences,skill,dialogs})
|
|
6028
|
-
}
|
|
6029
|
-
return{
|
|
6166
|
+
}})
|
|
6167
|
+
return{...model,width:toolbarPinWidth}}
|
|
6030
6168
|
|
|
6031
6169
|
|
|
6032
6170
|
|
|
@@ -6036,13 +6174,13 @@ return{pins,view,run,width:toolbarPinWidth}}
|
|
|
6036
6174
|
|
|
6037
6175
|
function ToolbarButton(props){const icons=useIcons()
|
|
6038
6176
|
const foreground=()=>props.reason?props.api.theme.current.textMuted:item.foregroundColor()
|
|
6039
|
-
const [hovered,setHovered]=
|
|
6177
|
+
const [hovered,setHovered]=createSignal35(false)
|
|
6040
6178
|
const item=useSidebarItem(props.api,props.interaction,{id:props.id,position:()=>({section:0,row:props.row + 1,column:props.column
|
|
6041
6179
|
}),activate:props.onRun
|
|
6042
6180
|
},()=>props.reason?props.api.theme.current.textMuted:props.api.theme.current.accent,"control")
|
|
6043
6181
|
const content=()=>[props.icons.map((icon)=>terminalIcon(icon,icons.style())).join(" "),props.text].filter(Boolean).join(" ")
|
|
6044
|
-
|
|
6045
|
-
|
|
6182
|
+
createEffect19(()=>props.onDetails(props.id,item.focused()||hovered()))
|
|
6183
|
+
onCleanup23(()=>props.onDetails(props.id,false))
|
|
6046
6184
|
return _$createComponent(Show27,{get when(){return _$memo(()=>!!(props.width===3&&props.icons.length===1))()&&!props.text
|
|
6047
6185
|
},get fallback(){return _$createComponent(SelectionBox,{get id(){return props.id
|
|
6048
6186
|
},ref(r$){var _ref$2=item.ref
|
|
@@ -6083,17 +6221,17 @@ setHovered(false)
|
|
|
6083
6221
|
}
|
|
6084
6222
|
function SidebarToolbar(props){const model=createToolbarModel(props)
|
|
6085
6223
|
const icons=useIcons()
|
|
6086
|
-
const [width,setWidth]=
|
|
6087
|
-
const [detail,setDetail]=
|
|
6088
|
-
const keys=
|
|
6089
|
-
const widths=
|
|
6090
|
-
const layout=
|
|
6091
|
-
const rows=
|
|
6092
|
-
const byKey=
|
|
6224
|
+
const [width,setWidth]=createSignal36(3)
|
|
6225
|
+
const [detail,setDetail]=createSignal36()
|
|
6226
|
+
const keys=createMemo16(()=>model.pins().map((pin)=>toolbarPinKey(pin)))
|
|
6227
|
+
const widths=createMemo16(()=>new Map(model.pins().map((pin)=>[toolbarPinKey(pin),model.width(pin)])))
|
|
6228
|
+
const layout=createMemo16(()=>toolbarLayout(keys(),width(),props.preferences.toolbarOverflow?.()??"menu",widths()))
|
|
6229
|
+
const rows=createMemo16(()=>layout().rows.map((_,index)=>index))
|
|
6230
|
+
const byKey=createMemo16(()=>new Map(model.pins().map((pin)=>[toolbarPinKey(pin),pin])))
|
|
6093
6231
|
const view=(key)=>{const pin=byKey().get(key)
|
|
6094
6232
|
return pin&&model.view(pin)
|
|
6095
6233
|
}
|
|
6096
|
-
const details=
|
|
6234
|
+
const details=createMemo16(()=>{if(detail()==="toolbar:more")
|
|
6097
6235
|
return "More pinned actions and Skills"
|
|
6098
6236
|
const item=view(detail()??"")
|
|
6099
6237
|
return item?[item.label,item.stateLabel,item.reason].filter(Boolean).join(" \xB7 "):undefined
|
|
@@ -6166,18 +6304,18 @@ return _el$
|
|
|
6166
6304
|
|
|
6167
6305
|
|
|
6168
6306
|
|
|
6169
|
-
function createSkillSectionModel(props,query){const target=
|
|
6170
|
-
const recent=
|
|
6171
|
-
const groups=
|
|
6172
|
-
const grouped=
|
|
6173
|
-
const list=
|
|
6174
|
-
const filtered=
|
|
6307
|
+
function createSkillSectionModel(props,query){const target=createMemo17(()=>props.controller.target())
|
|
6308
|
+
const recent=createMemo17(()=>new Map((props.preferences.recentSkills?.()??[]).map((location,index)=>[location,index])))
|
|
6309
|
+
const groups=createMemo17(()=>props.preferences.skillGroups?.()??{})
|
|
6310
|
+
const grouped=createMemo17(()=>Object.keys(groups()).length>0)
|
|
6311
|
+
const list=createMemo17(()=>buildSkillGroupedView(props.controller.list(target()),props.preferences.favoriteSkills?.()??new Set,groups(),recent()))
|
|
6312
|
+
const filtered=createMemo17(()=>list().filter((item)=>matchesFilter(query(),item.name,item.description,item.assignedGroup)))
|
|
6175
6313
|
const visibility=createListVisibility({items:filtered,limit:()=>props.preferences.sectionItemLimit?.("skills")??0,resetKey:()=>JSON.stringify([target().key,query()])
|
|
6176
6314
|
})
|
|
6177
|
-
const state=
|
|
6178
|
-
|
|
6315
|
+
const state=createMemo17(()=>props.controller.state(target()))
|
|
6316
|
+
createEffect20(()=>{const current=target()
|
|
6179
6317
|
const deactivate=untrack8(()=>props.controller.activate?.(current)??(()=>{}))
|
|
6180
|
-
|
|
6318
|
+
onCleanup24(deactivate)
|
|
6181
6319
|
untrack8(()=>void props.controller.refresh(current).catch(()=>{}))
|
|
6182
6320
|
})
|
|
6183
6321
|
async function useSkill(item){try{const isInserted=await props.controller.use(target(),item.name)
|
|
@@ -6238,7 +6376,7 @@ return _el$
|
|
|
6238
6376
|
}
|
|
6239
6377
|
function SkillsSection(props){const dialogs=useDialogs(props.api)
|
|
6240
6378
|
const toolbar=useToolbar()
|
|
6241
|
-
const [query,setQuery]=
|
|
6379
|
+
const [query,setQuery]=createSignal37("")
|
|
6242
6380
|
const model=createSkillSectionModel(props,query)
|
|
6243
6381
|
const navigationSection=()=>props.navigationSection??3
|
|
6244
6382
|
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"
|
|
@@ -6315,34 +6453,34 @@ return _el$
|
|
|
6315
6453
|
|
|
6316
6454
|
|
|
6317
6455
|
|
|
6318
|
-
function createSubagentSectionModel(props){const list=
|
|
6319
|
-
const recent=
|
|
6320
|
-
const rows=
|
|
6321
|
-
const [query,setQuery]=
|
|
6322
|
-
const [mode,setMode]=
|
|
6323
|
-
const counts=
|
|
6324
|
-
const tabs=
|
|
6325
|
-
const filtered=
|
|
6326
|
-
const parentID=
|
|
6327
|
-
const targetKey=
|
|
6328
|
-
|
|
6456
|
+
function createSubagentSectionModel(props){const list=createMemo18(()=>props.controller.list(props.sessionID))
|
|
6457
|
+
const recent=createMemo18(()=>props.controller.recent?.(props.sessionID)??[])
|
|
6458
|
+
const rows=createMemo18(()=>buildSubagentView(list(),recent()))
|
|
6459
|
+
const [query,setQuery]=createSignal38("")
|
|
6460
|
+
const [mode,setMode]=createSignal38("all")
|
|
6461
|
+
const counts=createMemo18(()=>countSubagentView(rows(),query()))
|
|
6462
|
+
const tabs=createMemo18(()=>["all","active","recent",...counts().errors>0?["errors"]:[]])
|
|
6463
|
+
const filtered=createMemo18(()=>filterSubagentView(rows(),mode(),query()))
|
|
6464
|
+
const parentID=createMemo18(()=>props.api.state?.session?.get(props.sessionID)?.parentID)
|
|
6465
|
+
const targetKey=createMemo18(()=>props.controller.target?.(props.sessionID).key??props.sessionID)
|
|
6466
|
+
createEffect21(()=>{targetKey()
|
|
6329
6467
|
setQuery("")
|
|
6330
6468
|
setMode("all")
|
|
6331
6469
|
})
|
|
6332
|
-
|
|
6470
|
+
createEffect21(()=>{if(mode()!=="all"&&counts()[mode()]===0)
|
|
6333
6471
|
setMode("all")
|
|
6334
6472
|
})
|
|
6335
6473
|
const visibility=createListVisibility({items:filtered,limit:()=>props.preferences.sectionItemLimit?.("subagents")??0,resetKey:()=>JSON.stringify([targetKey(),query(),mode()])
|
|
6336
6474
|
})
|
|
6337
|
-
const clockKey=
|
|
6475
|
+
const clockKey=createMemo18(()=>props.preferences.expanded().subagents&&visibility.visible().some((item)=>item.status.type!=="idle")?targetKey():undefined)
|
|
6338
6476
|
const now=createSubagentClock(clockKey)
|
|
6339
|
-
const byId=
|
|
6340
|
-
const ids=
|
|
6341
|
-
const state=
|
|
6342
|
-
|
|
6477
|
+
const byId=createMemo18(()=>new Map(visibility.visible().map((item)=>[item.session.id,item])))
|
|
6478
|
+
const ids=createMemo18(()=>visibility.visible().map((item)=>item.session.id))
|
|
6479
|
+
const state=createMemo18(()=>props.controller.state(props.sessionID))
|
|
6480
|
+
createEffect21(()=>{const sessionID=props.sessionID
|
|
6343
6481
|
targetKey()
|
|
6344
6482
|
const deactivate=untrack9(()=>props.controller.activate?.(sessionID)??(()=>{}))
|
|
6345
|
-
|
|
6483
|
+
onCleanup25(deactivate)
|
|
6346
6484
|
untrack9(()=>void props.controller.refresh(sessionID).catch(()=>{}))
|
|
6347
6485
|
})
|
|
6348
6486
|
return{list,recent,rows,query,setQuery,mode,setMode,counts,tabs,filtered,parentID,visibility,now,byId,ids,state
|
|
@@ -6729,28 +6867,28 @@ return _el$2
|
|
|
6729
6867
|
return _el$
|
|
6730
6868
|
}})
|
|
6731
6869
|
}
|
|
6732
|
-
function TodoSection(props){const list=
|
|
6870
|
+
function TodoSection(props){const list=createMemo19(()=>props.controller.list(props.sessionID))
|
|
6733
6871
|
const icons=useIcons()
|
|
6734
6872
|
const unavailable=()=>hostCapabilityUnavailable(props.api,"todo")
|
|
6735
6873
|
const managed=()=>("guidance" in props.controller)?props.controller:undefined
|
|
6736
6874
|
const native=()=>("source" in props.controller)&&props.controller.source==="native"
|
|
6737
6875
|
const setup=()=>("setup" in props.controller)?props.controller.setup:undefined
|
|
6738
6876
|
const setupState=()=>setup()?.state(props.sessionID)
|
|
6739
|
-
const [mode,setMode]=
|
|
6740
|
-
const targetKey=
|
|
6741
|
-
|
|
6877
|
+
const [mode,setMode]=createSignal39("all")
|
|
6878
|
+
const targetKey=createMemo19(()=>props.controller.target?.(props.sessionID).key??props.sessionID)
|
|
6879
|
+
createEffect22(()=>{targetKey()
|
|
6742
6880
|
setMode("all")
|
|
6743
6881
|
})
|
|
6744
|
-
const view=
|
|
6882
|
+
const view=createMemo19(()=>buildTodoView(list(),mode()))
|
|
6745
6883
|
const visibility=createListVisibility({items:()=>view().rows,limit:()=>props.preferences.sectionItemLimit?.("todo")??0,resetKey:()=>JSON.stringify([targetKey(),mode()])
|
|
6746
6884
|
})
|
|
6747
|
-
const state=
|
|
6748
|
-
|
|
6885
|
+
const state=createMemo19(()=>props.controller.state(props.sessionID))
|
|
6886
|
+
createEffect22(()=>{const sessionID=props.sessionID
|
|
6749
6887
|
targetKey()
|
|
6750
6888
|
if(unavailable())
|
|
6751
6889
|
return
|
|
6752
6890
|
const deactivate=untrack10(()=>props.controller.activate?.(sessionID)??(()=>{}))
|
|
6753
|
-
|
|
6891
|
+
onCleanup26(deactivate)
|
|
6754
6892
|
untrack10(()=>void props.controller.refresh(sessionID).catch(()=>{}))
|
|
6755
6893
|
untrack10(()=>void setup()?.refresh(sessionID).catch(()=>{}))
|
|
6756
6894
|
})
|
|
@@ -6819,8 +6957,8 @@ return _el$4
|
|
|
6819
6957
|
}})
|
|
6820
6958
|
}
|
|
6821
6959
|
function SidebarContent(props){const sections=props.preferences.sections
|
|
6822
|
-
const visibleSections=
|
|
6823
|
-
|
|
6960
|
+
const visibleSections=createMemo20(()=>props.preferences.sectionOrder().filter((section)=>sections()[section]&&supportsSidebarSection(props.api,section)))
|
|
6961
|
+
onCleanup27(()=>props.interaction.setContentRoot(undefined))
|
|
6824
6962
|
return _$createComponent(ToolbarProvider,{get api(){return props.api
|
|
6825
6963
|
},get preferences(){return props.preferences
|
|
6826
6964
|
},get skills(){return props.skills
|
|
@@ -6871,8 +7009,8 @@ return _el$
|
|
|
6871
7009
|
}
|
|
6872
7010
|
|
|
6873
7011
|
|
|
6874
|
-
function McpPersistence(props){const persist=
|
|
6875
|
-
|
|
7012
|
+
function McpPersistence(props){const persist=createMemo21(()=>props.controller.persist())
|
|
7013
|
+
createEffect23(()=>{if(!props.api.state.ready)
|
|
6876
7014
|
return
|
|
6877
7015
|
persist()
|
|
6878
7016
|
const route=props.api.route.current
|
|
@@ -6880,12 +7018,12 @@ const params="params" in route?route.params:undefined
|
|
|
6880
7018
|
if(typeof params?.sessionID!=="string")
|
|
6881
7019
|
return
|
|
6882
7020
|
const current=props.controller.target()
|
|
6883
|
-
|
|
7021
|
+
onCleanup28(()=>props.controller.deactivate(current))
|
|
6884
7022
|
untrack11(()=>void props.controller.activate(current).catch(()=>{}))
|
|
6885
7023
|
})
|
|
6886
7024
|
return _$createElement("box")
|
|
6887
7025
|
}
|
|
6888
|
-
function PreferencesPersistence(props){
|
|
7026
|
+
function PreferencesPersistence(props){createEffect23(()=>{const location=currentLocation(props.api)
|
|
6889
7027
|
untrack11(()=>props.controller.setActiveScope(preferencesScope({directory:location.routing.directory,worktree:props.api.state.path.worktree
|
|
6890
7028
|
})))
|
|
6891
7029
|
props.controller.load()
|
|
@@ -6893,7 +7031,7 @@ props.controller.load()
|
|
|
6893
7031
|
return _$createElement("box")
|
|
6894
7032
|
}
|
|
6895
7033
|
function FirstRunWizardPersistence(props){let isChecked=false
|
|
6896
|
-
|
|
7034
|
+
createEffect23(()=>{if(isChecked)
|
|
6897
7035
|
return
|
|
6898
7036
|
isChecked=true
|
|
6899
7037
|
showFirstRunWizard(props.api,props.preferences).catch(()=>{})
|
|
@@ -6911,7 +7049,7 @@ return _$createElement("box")
|
|
|
6911
7049
|
|
|
6912
7050
|
function SidebarTitle(props){const icons=useIcons()
|
|
6913
7051
|
const theme=()=>props.api.theme.current
|
|
6914
|
-
const created=
|
|
7052
|
+
const created=createMemo22(()=>{const value=props.api.state.session.get(props.sessionID)?.time?.created
|
|
6915
7053
|
return value===undefined?undefined:`Created ${new Date(value).toLocaleDateString("en", {
|
|
6916
7054
|
dateStyle: "medium"
|
|
6917
7055
|
})}`
|
|
@@ -6920,7 +7058,7 @@ const settingsId=`${PLUGIN_ID}.settings`
|
|
|
6920
7058
|
const settings=useSidebarItem(props.api,props.interaction,{id:settingsId,position:{section:0,row:0,column:0
|
|
6921
7059
|
},activate:()=>openSettings(props.api,props.preferences,undefined,props.mcp,props.skills)
|
|
6922
7060
|
},()=>theme().textMuted,"control")
|
|
6923
|
-
|
|
7061
|
+
onCleanup29(()=>props.interaction.setTitleRoot(undefined))
|
|
6924
7062
|
return(()=>{var _el$=_$createElement("box"),_el$2=_$createElement("box"),_el$3=_$createElement("box")
|
|
6925
7063
|
_$insertNode(_el$,_el$2)
|
|
6926
7064
|
_$use((node)=>props.interaction.setTitleRoot(node),_el$)
|
|
@@ -6980,40 +7118,10 @@ const [user,project]=await Promise.all([safe(userPath?readSource(userPath,()=>re
|
|
|
6980
7118
|
return mergeConfiguredDefaults(configuredDefaultsFromPluginOptions(options),user,project)
|
|
6981
7119
|
}
|
|
6982
7120
|
|
|
6983
|
-
|
|
6984
|
-
var scheduleInterval=(callback,milliseconds)=>{const timer=setInterval(callback,milliseconds)
|
|
6985
|
-
return()=>clearInterval(timer)
|
|
6986
|
-
}
|
|
6987
|
-
function createLimitsRefresh(options,schedule=scheduleInterval){let disposed=false
|
|
6988
|
-
const selectedKey=createMemo22(()=>JSON.stringify(options.selectedModel?.()))
|
|
6989
|
-
const targetKey=createMemo22(()=>JSON.stringify(options.controller.current().model))
|
|
6990
|
-
const interval=createMemo22(()=>(parseLimitsRefreshMinutes(options.refreshMinutes?.())??DEFAULT_LIMITS_REFRESH_MINUTES)*60000)
|
|
6991
|
-
createEffect23(on2(selectedKey,()=>{const model=options.selectedModel?.()
|
|
6992
|
-
if(model&&options.accountSource)
|
|
6993
|
-
options.accountSource.refresh(model).catch(()=>{})
|
|
6994
|
-
}))
|
|
6995
|
-
createEffect23(on2(targetKey,()=>{const{model,adapter}=options.controller.current()
|
|
6996
|
-
if(model&&adapter)
|
|
6997
|
-
options.controller.refresh()
|
|
6998
|
-
}))
|
|
6999
|
-
async function refresh(){if(disposed)
|
|
7000
|
-
return
|
|
7001
|
-
const target=targetKey()
|
|
7002
|
-
const model=options.selectedModel?.()
|
|
7003
|
-
if(model&&options.accountSource)
|
|
7004
|
-
await options.accountSource.refresh(model)
|
|
7005
|
-
if(!disposed&&target===targetKey())
|
|
7006
|
-
await options.controller.refresh()
|
|
7007
|
-
}
|
|
7008
|
-
createEffect23(on2(interval,(milliseconds)=>{onCleanup29(schedule(()=>void refresh().catch(()=>{}),milliseconds))
|
|
7009
|
-
}))
|
|
7010
|
-
onCleanup29(()=>{disposed=true
|
|
7011
|
-
})
|
|
7012
|
-
}
|
|
7013
7121
|
function LimitsPersistence(props){createLimitsRefresh(props)
|
|
7014
7122
|
return _$createElement("box")
|
|
7015
7123
|
}
|
|
7016
|
-
function bindNavigatorAbout(api,status,updates,notes){const dispose=registerNavigatorAboutServices(api,{navigatorVersion:"0.
|
|
7124
|
+
function bindNavigatorAbout(api,status,updates,notes){const dispose=registerNavigatorAboutServices(api,{navigatorVersion:"0.27.0",openCodeVersion:api.app.version,checkState:()=>status.navigatorCheckState?.()??{status:"idle"},checking:()=>status.navigatorCheckState?.().status==="checking",updating:updates.navigatorUpdating,installed:updates.navigatorInstalled,check:()=>status.refreshNavigator?.()??Promise.resolve("unavailable"),update(dialogs){const target=status.navigatorUpdate()
|
|
7017
7125
|
if(target)
|
|
7018
7126
|
updates.navigator(target,dialogs)
|
|
7019
7127
|
},changelog:async ()=>notes.parseChangelog(await notes.readBundledChangelog())
|
|
@@ -7149,7 +7257,7 @@ context.keymap.dispatch(command.id)
|
|
|
7149
7257
|
context.renderer.keyInput.on("keypress",onKeypress)
|
|
7150
7258
|
const keymap={registerLayer(layer){const id=++sequence
|
|
7151
7259
|
const owner=getOwner()
|
|
7152
|
-
const [active,setActive]=
|
|
7260
|
+
const [active,setActive]=createSignal40(true)
|
|
7153
7261
|
const install=()=>{context.keymap.layer(()=>({mode:typeof layer.mode==="string"?layer.mode:"base",priority:layer.priority,enabled:()=>active()&&enabled(layer.enabled),target:layer.target?()=>layer.target:undefined,commands:v2LayerCommands(id,layer,()=>true,run,context.keymap.dispatch)
|
|
7154
7262
|
}))
|
|
7155
7263
|
}
|
|
@@ -7194,7 +7302,7 @@ cleanups.clear()
|
|
|
7194
7302
|
context.renderer.keyInput.off("keypress",onKeypress)
|
|
7195
7303
|
}}}
|
|
7196
7304
|
|
|
7197
|
-
function createV2SessionAdapter(context){const [retryDetails,setRetryDetails]=
|
|
7305
|
+
function createV2SessionAdapter(context){const [retryDetails,setRetryDetails]=createSignal41({})
|
|
7198
7306
|
const projections=new WeakMap
|
|
7199
7307
|
function normalize(info){const directory=info.location.directory
|
|
7200
7308
|
const workspaceID=context.location?.directory===directory?context.location.workspaceID:undefined
|
|
@@ -7361,48 +7469,18 @@ return parseTodos(item.state.input.todos)
|
|
|
7361
7469
|
}}
|
|
7362
7470
|
return []
|
|
7363
7471
|
}
|
|
7364
|
-
function createNativeTodoController(context,api){const
|
|
7365
|
-
const pending=new Map
|
|
7366
|
-
let activeTarget
|
|
7367
|
-
function target(sessionID){const session=api.state.session.get(sessionID)
|
|
7472
|
+
function createNativeTodoController(context,api){function target(sessionID){const session=api.state.session.get(sessionID)
|
|
7368
7473
|
const directory=session?.directory??api.state.path.directory
|
|
7369
7474
|
const workspace=session?.workspaceID
|
|
7370
7475
|
return{key:JSON.stringify([sessionID,directory,workspace??null]),sessionID,routing:{directory,...workspace&&{workspace}}}}
|
|
7371
7476
|
function list(sessionID){return nativeTodos(context.data.session.message.list(sessionID),context.data.session.get(sessionID)?.revert?.messageID)
|
|
7372
7477
|
}
|
|
7373
|
-
|
|
7374
|
-
|
|
7375
|
-
|
|
7376
|
-
const existing=pending.get(current.key)
|
|
7377
|
-
if(existing&&!force)
|
|
7378
|
-
return existing
|
|
7379
|
-
const requestState=requests.start(current.key,"refresh native todos",context.data.session.message.list(sessionID).length>0,force)
|
|
7380
|
-
if(!requestState)
|
|
7381
|
-
return existing
|
|
7382
|
-
const request=Promise.try(()=>Promise.all([context.data.session.sync(sessionID),context.data.session.message.sync(sessionID)])).then(()=>{if(!requestState.isCurrent())
|
|
7383
|
-
return []
|
|
7384
|
-
requestState.succeed()
|
|
7478
|
+
return{source:"native",...createTodoModel({lifecycle:api.lifecycle,target,cache:"source",hasValue:(sessionID)=>context.data.session.message.list(sessionID).length>0,source:{list,async refresh(sessionID,signal){signal.throwIfAborted()
|
|
7479
|
+
await Promise.all([context.data.session.sync(sessionID),context.data.session.message.sync(sessionID)])
|
|
7480
|
+
signal.throwIfAborted()
|
|
7385
7481
|
return list(sessionID)
|
|
7386
|
-
})
|
|
7387
|
-
|
|
7388
|
-
}).finally(()=>{requestState.finish()
|
|
7389
|
-
if(pending.get(current.key)===request)
|
|
7390
|
-
pending.delete(current.key)
|
|
7391
|
-
})
|
|
7392
|
-
pending.set(current.key,request)
|
|
7393
|
-
return request
|
|
7394
|
-
}
|
|
7395
|
-
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
|
|
7396
|
-
if(activeTarget!==key){requests.abortAll()
|
|
7397
|
-
pending.clear()
|
|
7398
|
-
activeTarget=key
|
|
7399
|
-
}
|
|
7400
|
-
return()=>{if(activeTarget!==key)
|
|
7401
|
-
return
|
|
7402
|
-
activeTarget=undefined
|
|
7403
|
-
requests.abortAll()
|
|
7404
|
-
pending.clear()
|
|
7405
|
-
}}}}
|
|
7482
|
+
}}})
|
|
7483
|
+
}}
|
|
7406
7484
|
function collectionLocation(target){return{directory:target.routing.directory??"",...target.routing.workspace&&{workspaceID:target.routing.workspace}}}
|
|
7407
7485
|
async function syncCollection(collection,target,force,signal){signal.throwIfAborted()
|
|
7408
7486
|
const ref=collectionLocation(target)
|
|
@@ -7411,9 +7489,9 @@ collection.invalidate(ref)
|
|
|
7411
7489
|
await collection.sync(ref)
|
|
7412
7490
|
signal.throwIfAborted()
|
|
7413
7491
|
}
|
|
7414
|
-
function
|
|
7492
|
+
function createNativeMcpSource(data){const collection=()=>data().location.mcp.server
|
|
7415
7493
|
const projections=new WeakMap
|
|
7416
|
-
const list=(target)=>(collection.list(collectionLocation(target))??[]).map((server)=>{let item=projections.get(server)
|
|
7494
|
+
const list=(target)=>(collection().list(collectionLocation(target))??[]).map((server)=>{let item=projections.get(server)
|
|
7417
7495
|
if(!item){item={get name(){return server.name
|
|
7418
7496
|
},get title(){return server.title
|
|
7419
7497
|
},get status(){return server.status.status
|
|
@@ -7423,12 +7501,17 @@ projections.set(server,item)
|
|
|
7423
7501
|
}
|
|
7424
7502
|
return item
|
|
7425
7503
|
})
|
|
7426
|
-
return{list,async refresh(target,force,signal){
|
|
7504
|
+
return{list,async refresh(target,force,signal){const current=collection()
|
|
7505
|
+
await syncCollection(current,target,force,signal)
|
|
7506
|
+
if(collection()!==current)
|
|
7507
|
+
throw new DOMException("OpenCode connection changed","AbortError")
|
|
7427
7508
|
return list(target)
|
|
7428
7509
|
}}}
|
|
7429
|
-
function
|
|
7430
|
-
|
|
7431
|
-
|
|
7510
|
+
function createV2McpSource(context){return createNativeMcpSource(()=>context.data)
|
|
7511
|
+
}
|
|
7512
|
+
function createNativeSkillSource(input){const projections=new WeakMap
|
|
7513
|
+
const collection=()=>input.data().location.skill
|
|
7514
|
+
const list=(target)=>(collection().list(collectionLocation(target))??[]).map((skill)=>{let item=projections.get(skill)
|
|
7432
7515
|
if(!item){item={get id(){return skill.id
|
|
7433
7516
|
},get name(){return skill.name
|
|
7434
7517
|
},get description(){return skill.description
|
|
@@ -7439,34 +7522,49 @@ projections.set(skill,item)
|
|
|
7439
7522
|
}
|
|
7440
7523
|
return item
|
|
7441
7524
|
})
|
|
7442
|
-
return{list,async refresh(target,force,signal){
|
|
7525
|
+
return{list,async refresh(target,force,signal){const current=collection()
|
|
7526
|
+
await syncCollection(current,target,force,signal)
|
|
7527
|
+
if(collection()!==current)
|
|
7528
|
+
throw new DOMException("OpenCode connection changed","AbortError")
|
|
7443
7529
|
return list(target)
|
|
7444
7530
|
},async use(target,skill,signal){signal.throwIfAborted()
|
|
7445
|
-
const route=context.ui.router.current()
|
|
7446
|
-
const session=route.type==="session"&&context.data.session.get(route.sessionID)
|
|
7447
7531
|
const actual=list(target).find((item)=>item.id===skill.id&&item.location===skill.location)
|
|
7448
|
-
if(
|
|
7532
|
+
if(!actual?.id)
|
|
7449
7533
|
throw new Error("Skill target changed; select the source again")
|
|
7450
|
-
|
|
7451
|
-
return !signal.aborted
|
|
7534
|
+
return input.use(target,actual,signal)
|
|
7452
7535
|
}}}
|
|
7453
|
-
function
|
|
7454
|
-
|
|
7455
|
-
|
|
7536
|
+
function createV2SkillSource(context){return createNativeSkillSource({data:()=>context.data,async use(target,skill,signal){const route=context.ui.router.current()
|
|
7537
|
+
const session=route.type==="session"&&context.data.session.get(route.sessionID)
|
|
7538
|
+
if(route.type!=="session"||!session||session.location.directory!==target.routing.directory||!skill.id)
|
|
7539
|
+
throw new Error("Skill target changed; select the source again")
|
|
7540
|
+
await context.client.experimental.session.skill({sessionID:route.sessionID,id:skill.id},{signal})
|
|
7541
|
+
return !signal.aborted
|
|
7542
|
+
}})
|
|
7543
|
+
}
|
|
7544
|
+
function createNativeSubagentSource(input){return{list:(parentID)=>input.sessions().list().filter((item)=>item.parentID===parentID).flatMap((item)=>{const projected=input.project(item)
|
|
7545
|
+
return projected?[projected]:[]
|
|
7546
|
+
}),status:input.status,startedAt(id){const sessions=input.sessions()
|
|
7547
|
+
if(sessions.status(id)!=="running")
|
|
7456
7548
|
return
|
|
7457
|
-
const time=
|
|
7549
|
+
const time=sessions.get(id)?.time
|
|
7458
7550
|
if(!time?.busy||time.idle!==undefined&&time.idle>=time.busy)
|
|
7459
7551
|
return
|
|
7460
7552
|
return time.busy
|
|
7461
7553
|
},async refresh(parentID,signal){signal.throwIfAborted()
|
|
7554
|
+
const client=input.client()
|
|
7555
|
+
const sessions=input.sessions()
|
|
7462
7556
|
let cursor
|
|
7463
|
-
do{const page=await
|
|
7464
|
-
|
|
7465
|
-
|
|
7557
|
+
do{const page=await client.session.list(cursor?{cursor,limit:100}:{parentID,limit:100},{signal})
|
|
7558
|
+
signal.throwIfAborted()
|
|
7559
|
+
if(input.client()!==client||input.sessions()!==sessions)
|
|
7560
|
+
throw new DOMException("Subagent connection changed","AbortError")
|
|
7561
|
+
await Promise.all(page.data.filter((item)=>!sessions.get(item.id)).map((item)=>sessions.sync(item.id)))
|
|
7466
7562
|
cursor=page.cursor.next??undefined
|
|
7467
7563
|
signal.throwIfAborted()
|
|
7468
7564
|
} while(cursor)
|
|
7469
7565
|
}}}
|
|
7566
|
+
function createV2SubagentSource(context,api){return createNativeSubagentSource({sessions:()=>context.data.session,client:()=>context.client,project:(info)=>api.state.session.get(info.id),status:(id)=>api.state.session.status(id)??{type:"idle"}})
|
|
7567
|
+
}
|
|
7470
7568
|
function createOpenCodeV2Sources(context,api){return{skills:createV2SkillSource(context),mcp:createV2McpSource(context),subagents:createV2SubagentSource(context,api)
|
|
7471
7569
|
}}
|
|
7472
7570
|
function loadNavigatorUpdates(){const path=import.meta.url.includes("/dist/tui.js")?"./navigator-updates.js":"../navigator-updates"
|
|
@@ -7488,7 +7586,7 @@ const limitsPath=import.meta.url.includes("/dist/tui.js")?"./provider-limits.js"
|
|
|
7488
7586
|
const limitsModule=await import(limitsPath)
|
|
7489
7587
|
const LimitsSection=limitsModule.ProviderLimitsSection
|
|
7490
7588
|
const{controller:limits,codex,accountSource,selectModel,modelSelection
|
|
7491
|
-
}=limitsModule.createProviderQuotaIntegration(api,preferences,"0.
|
|
7589
|
+
}=limitsModule.createProviderQuotaIntegration(api,preferences,"0.27.0",hostContext)
|
|
7492
7590
|
const mcp=createMcpController(api,preferences.persistMcp,preferences,nativeSources?.mcp)
|
|
7493
7591
|
const interaction=createSidebarInteraction(api,()=>openKeyboardHelp(api,preferences.lspIconStyle,preferences.cornerFont,sidebarShortcutActions(api)))
|
|
7494
7592
|
const startup=createStartupSessionController(api,preferences)
|
|
@@ -7517,7 +7615,7 @@ api.slots.register({order:100,slots:{app(){return _$createComponent(IconProvider
|
|
|
7517
7615
|
},interaction,skills,subagents,mcp
|
|
7518
7616
|
}),_$createComponent(FirstRunWizardPersistence,{api,preferences
|
|
7519
7617
|
}),_$createComponent(StartupSessionBinding,{api,controller:startup
|
|
7520
|
-
}),_$createComponent(UpgradeNotesBinding,{api,preferences,version:"0.
|
|
7618
|
+
}),_$createComponent(UpgradeNotesBinding,{api,preferences,version:"0.27.0"
|
|
7521
7619
|
}),_$createComponent(McpPersistence,{api,controller:mcp
|
|
7522
7620
|
})]
|
|
7523
7621
|
}})
|
|
@@ -7551,13 +7649,13 @@ return result.data?.type==="text"?result.data.content:undefined
|
|
|
7551
7649
|
const updateServices=await loadNavigatorUpdates()
|
|
7552
7650
|
const{createVersionStatus,createVersionUpdateActions,createOpenCodeV1VersionUpdater
|
|
7553
7651
|
}=updateServices
|
|
7554
|
-
const versionStatus=createVersionStatus(api,"0.
|
|
7555
|
-
const versionUpdates=createVersionUpdateActions(api,versionStatus,createOpenCodeV1VersionUpdater(api,meta),()=>preferences.rememberNavigatorVersionBeforeUpdate("0.
|
|
7652
|
+
const versionStatus=createVersionStatus(api,"0.27.0")
|
|
7653
|
+
const versionUpdates=createVersionUpdateActions(api,versionStatus,createOpenCodeV1VersionUpdater(api,meta),()=>preferences.rememberNavigatorVersionBeforeUpdate("0.27.0"))
|
|
7556
7654
|
bindNavigatorAbout(api,versionStatus,versionUpdates,updateServices)
|
|
7557
7655
|
api.slots.register({order:90,slots:{sidebar_footer(_context,props){return _$createComponent(IconProvider,{get style(){return preferences.lspIconStyle
|
|
7558
7656
|
},get multilineCorners(){return preferences.cornerFont
|
|
7559
7657
|
},get children(){return _$createComponent(VersionFooter,{api,get sessionID(){return props.session_id
|
|
7560
|
-
},navigatorVersion:"0.
|
|
7658
|
+
},navigatorVersion:"0.27.0",status:versionStatus,get onOpenCodeUpdate(){return versionUpdates.openCode
|
|
7561
7659
|
},get onNavigatorUpdate(){return versionUpdates.navigator
|
|
7562
7660
|
}})
|
|
7563
7661
|
}})
|
|
@@ -7574,8 +7672,8 @@ return new TextDecoder().decode(await context.client.file.read({location:context
|
|
|
7574
7672
|
const updateServices=await loadNavigatorUpdates()
|
|
7575
7673
|
const{createVersionStatus,createVersionUpdateActions,createOpenCodeV2VersionUpdater
|
|
7576
7674
|
}=updateServices
|
|
7577
|
-
const versionStatus=createVersionStatus(adapter.api,"0.
|
|
7578
|
-
const versionUpdates=createVersionUpdateActions(adapter.api,versionStatus,createOpenCodeV2VersionUpdater(context),()=>preferences.rememberNavigatorVersionBeforeUpdate("0.
|
|
7675
|
+
const versionStatus=createVersionStatus(adapter.api,"0.27.0")
|
|
7676
|
+
const versionUpdates=createVersionUpdateActions(adapter.api,versionStatus,createOpenCodeV2VersionUpdater(context),()=>preferences.rememberNavigatorVersionBeforeUpdate("0.27.0"))
|
|
7579
7677
|
bindNavigatorAbout(adapter.api,versionStatus,versionUpdates,updateServices)
|
|
7580
7678
|
const disposeFooter=context.ui.slot({append:"sidebar.footer",render:()=>_$createComponent(IconProvider,{get style(){return preferences.lspIconStyle
|
|
7581
7679
|
},get multilineCorners(){return preferences.cornerFont
|
|
@@ -7583,7 +7681,7 @@ const disposeFooter=context.ui.slot({append:"sidebar.footer",render:()=>_$create
|
|
|
7583
7681
|
_$setProp(_el$,"flexDirection","row")
|
|
7584
7682
|
_$setProp(_el$,"justifyContent","space-between")
|
|
7585
7683
|
_$insert(_el$,_$createComponent(VersionSummary,{get api(){return adapter.api
|
|
7586
|
-
},navigatorVersion:"0.
|
|
7684
|
+
},navigatorVersion:"0.27.0",status:versionStatus,get onOpenCodeUpdate(){return versionUpdates.openCode
|
|
7587
7685
|
},get onNavigatorUpdate(){return versionUpdates.navigator
|
|
7588
7686
|
}}),null)
|
|
7589
7687
|
_$insert(_el$,_$createComponent(SettingsFooterButton,{get api(){return adapter.api
|