opencode-navigator 0.17.2 → 0.18.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 +13 -8
- package/README.md +26 -5
- package/dist/rpc.js +15 -0
- package/dist/server.js +72 -0
- package/dist/tui.js +194 -49
- package/package.json +9 -1
- package/rpc.js +1 -0
- package/server.js +1 -0
package/CHANGELOG.md
CHANGED
|
@@ -2,17 +2,22 @@
|
|
|
2
2
|
|
|
3
3
|
## Unreleased
|
|
4
4
|
|
|
5
|
+
## [0.18.0] - 2026-10-01
|
|
6
|
+
|
|
7
|
+
- Add durable per-session Todo lists to OpenCode 2.x through a separately configured Navigator server plugin and an agent Todo tool.
|
|
8
|
+
- Update Todo in the sidebar as tasks change, and offer an off-by-default per-session switch for model-context Todo instructions.
|
|
9
|
+
- Keep Todo visible with setup guidance when the OpenCode 2.x server plugin is missing.
|
|
10
|
+
|
|
11
|
+
## [0.17.3] - 2026-09-30
|
|
12
|
+
|
|
5
13
|
## [0.17.2] - 2026-09-30
|
|
6
14
|
|
|
7
|
-
-
|
|
8
|
-
-
|
|
9
|
-
- Make test version expectations independent of the current Navigator and OpenCode releases.
|
|
15
|
+
- Update a pinned local Navigator installation from its version label while keeping its file or directory source unchanged.
|
|
16
|
+
- Hide the session title and creation date independently with Global/Worktree settings in OpenCode 1.x.
|
|
10
17
|
|
|
11
18
|
## [0.17.1] - 2026-09-29
|
|
12
19
|
|
|
13
|
-
-
|
|
14
|
-
- Stop tracking project-local OpenCode TUI configuration; ignore both TUI and CLI config files without removing existing local settings.
|
|
15
|
-
- Let real-host smoke tests verify pinned plugin installations with isolated configurations.
|
|
20
|
+
- Fix the local Navigator installation changing unexpectedly when rebuilding the repository; it now stays on its pinned version.
|
|
16
21
|
|
|
17
22
|
## [0.17.0] - 2026-09-29
|
|
18
23
|
|
|
@@ -23,16 +28,16 @@
|
|
|
23
28
|
|
|
24
29
|
- Make the entire OpenCode or Navigator version label open its own update confirmation when an update is available. The separator and the other version remain inactive.
|
|
25
30
|
- Replace the small update arrow with a more prominent filled-circle Nerd Font indicator, retaining an ASCII fallback.
|
|
26
|
-
- Keep version-display assertions independent of release numbers.
|
|
27
31
|
|
|
28
32
|
## [0.16.0] - 2026-09-25
|
|
29
33
|
|
|
30
34
|
- Show both OpenCode and Navigator versions in the OpenCode 2.x footer.
|
|
31
35
|
- Confirm updates from the footer or command palette, preserve the original installation method and scope, and report the outcome with a restart reminder.
|
|
32
|
-
- Refresh the deterministic screenshot gallery and keep the unminified bundle within its size limit.
|
|
33
36
|
|
|
34
37
|
Earlier release notes are available on [GitHub Releases](https://github.com/St1ggy/opencode-navigator/releases).
|
|
35
38
|
|
|
39
|
+
[0.18.0]: https://github.com/St1ggy/opencode-navigator/compare/v0.17.3...v0.18.0
|
|
40
|
+
[0.17.3]: https://github.com/St1ggy/opencode-navigator/compare/v0.17.2...v0.17.3
|
|
36
41
|
[0.17.2]: https://github.com/St1ggy/opencode-navigator/compare/v0.17.1...v0.17.2
|
|
37
42
|
[0.17.1]: https://github.com/St1ggy/opencode-navigator/compare/v0.17.0...v0.17.1
|
|
38
43
|
[0.17.0]: https://github.com/St1ggy/opencode-navigator/compare/v0.16.1...v0.17.0
|
package/README.md
CHANGED
|
@@ -12,7 +12,7 @@ See the [changelog](CHANGELOG.md) for release-by-release changes.
|
|
|
12
12
|
|
|
13
13
|
- Theme-aware session title with the session creation date
|
|
14
14
|
- First-run setup guide with interactive section settings
|
|
15
|
-
- Collapsible Todo section with status filters, grouped tasks, progress and priority indicators
|
|
15
|
+
- Collapsible Todo section with status filters, grouped tasks, progress and priority indicators; OpenCode 2 adds session-owned tasks and optional model-context instructions
|
|
16
16
|
- Active subagent list with live statuses and click-to-open navigation, including dev-team workers running in separate local processes
|
|
17
17
|
- Compact, searchable workspace skill list with user-wide favorites, recent skills, source details, and click-to-confirm slash commands
|
|
18
18
|
- Configurable host quick actions, including the auto-approve toggle, with user-wide bookmarks and availability reasons
|
|
@@ -42,8 +42,9 @@ collapsed. Use `Save current layout as default` in sidebar settings to reuse the
|
|
|
42
42
|
current visible/hidden, expanded/collapsed, and ordering states in new sessions.
|
|
43
43
|
|
|
44
44
|
Supports OpenCode 1.18.30 and newer, including OpenCode 2.x. OpenCode 2.0.16 does
|
|
45
|
-
not expose Todo or LSP data to TUI plugins. Navigator
|
|
46
|
-
|
|
45
|
+
not expose host Todo or LSP data to TUI plugins. Navigator supplies its own
|
|
46
|
+
session Todo list through a separately configured server plugin in 2.x. Without
|
|
47
|
+
that plugin, Todo stays visible with setup guidance. LSP is hidden on 2.x while retaining Subagents,
|
|
47
48
|
Skills, Quick Actions, MCP, Search, settings, and presets. All interface icons use Nerd Font glyphs by
|
|
48
49
|
default (Codicons for controls, keyboard symbols for hints, language logos for LSP). Use a Nerd Fonts v3
|
|
49
50
|
terminal font, or select **Settings → Behavior → Icon style → Text fallback**.
|
|
@@ -168,6 +169,26 @@ OpenCode 2.x CLI plugins are global terminal settings; there is no project-local
|
|
|
168
169
|
plugin overrides are required. OpenCode validates `cli.json` strictly, so keep it
|
|
169
170
|
within the linked schema and restart OpenCode after changing it.
|
|
170
171
|
|
|
172
|
+
To enable Todo in OpenCode 2.x, also install the **server** half of Navigator.
|
|
173
|
+
Add the same package to `~/.config/opencode/opencode.json` (or the project
|
|
174
|
+
`opencode.json`):
|
|
175
|
+
|
|
176
|
+
```json
|
|
177
|
+
{
|
|
178
|
+
"$schema": "https://opencode.ai/config.json",
|
|
179
|
+
"plugin": ["opencode-navigator"]
|
|
180
|
+
}
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
For a local source installation, use the directory containing Navigator's
|
|
184
|
+
`server.js` in the `plugin` array. Keep the TUI package in `cli.json` as above;
|
|
185
|
+
the server configuration alone does not replace it. Restart OpenCode after
|
|
186
|
+
configuring both. Todo items belong to the current session, survive restarts,
|
|
187
|
+
and update in the sidebar when the agent calls `navigator_todo_write`. The
|
|
188
|
+
**Todo instructions: Off/On** control in the Todo section is session-scoped and
|
|
189
|
+
starts **Off**: tasks and the agent tool work without adding Todo instructions
|
|
190
|
+
to the model's context. OpenCode 1.x continues to show the host's Todo list.
|
|
191
|
+
|
|
171
192
|
### Install the corner font
|
|
172
193
|
|
|
173
194
|
**Required for rounded multiline selections in Nerd Font mode.** Run the font
|
|
@@ -509,8 +530,8 @@ root order. Activate any badge, including a custom server, to toggle its full ID
|
|
|
509
530
|
in place. Navigator does not open a root/status dialog because OpenCode may report
|
|
510
531
|
an empty root and does not expose the underlying diagnostic error text.
|
|
511
532
|
|
|
512
|
-
Todo priorities are read-only
|
|
513
|
-
|
|
533
|
+
Todo priorities are read-only in the sidebar. OpenCode 1.x provides host Todo
|
|
534
|
+
data without a TUI mutation API; on 2.x, Navigator's agent tool writes tasks.
|
|
514
535
|
|
|
515
536
|
Todo offers `All`, `Active`, and `Finished` views with counts. Active shows running
|
|
516
537
|
tasks before pending tasks. Finished contains separate Completed and Cancelled
|
package/dist/rpc.js
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
var item={type:"object",properties:{content:{type:"string",minLength:1,maxLength:512},status:{type:"string",enum:["pending","in_progress","completed","cancelled"]},priority:{type:"string",enum:["high","medium","low"]}},required:["content","status"],additionalProperties:false
|
|
2
|
+
}
|
|
3
|
+
var todos={type:"array",items:item,maxItems:100}
|
|
4
|
+
var sessionID={type:"string",minLength:1}
|
|
5
|
+
var output={type:"object",properties:{todos,guidance:{type:"boolean"}},required:["todos","guidance"],additionalProperties:false
|
|
6
|
+
}
|
|
7
|
+
var NavigatorTodoRpc={id:"opencode-navigator.todo",methods:{list:{input:{type:"object",properties:{sessionID},required:["sessionID"],additionalProperties:false},output
|
|
8
|
+
},replace:{input:{type:"object",properties:{sessionID,todos},required:["sessionID","todos"],additionalProperties:false
|
|
9
|
+
},output
|
|
10
|
+
},guidance:{input:{type:"object",properties:{sessionID,enabled:{type:"boolean"}},required:["sessionID","enabled"],additionalProperties:false
|
|
11
|
+
},output
|
|
12
|
+
}},events:{updated:{schema:{type:"object",properties:{sessionID,todos,guidance:{type:"boolean"}},required:["sessionID","todos","guidance"],additionalProperties:false
|
|
13
|
+
}}}}
|
|
14
|
+
export{NavigatorTodoRpc
|
|
15
|
+
}
|
package/dist/server.js
ADDED
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import {Plugin} from "@opencode/plugin"
|
|
2
|
+
function normalizeTodoState(value){if(!value||typeof value!=="object")
|
|
3
|
+
return{todos:[],guidance:false}
|
|
4
|
+
const state=value
|
|
5
|
+
const statuses=new Set(["pending","in_progress","completed","cancelled"])
|
|
6
|
+
const priorities=new Set(["high","medium","low"])
|
|
7
|
+
const todos=Array.isArray(state.todos)?state.todos.filter((item)=>item&&typeof item.content==="string"&&item.content.trim().length>0&&item.content.length<=512&&statuses.has(item.status)).slice(0,100).map((item)=>({content:item.content.trim(),status:item.status,...priorities.has(item.priority??"")&&{priority:item.priority}})):[]
|
|
8
|
+
return{todos,guidance:state.guidance===true}}
|
|
9
|
+
function todoGuidance(state){const lines=state.todos.map((todo)=>`- [${todo.status}] ${todo.content}`)
|
|
10
|
+
return ["Navigator Todo: when work has multiple steps, use navigator_todo_write to keep the session Todo list current.","Mark work in progress, completed, or cancelled as it changes; avoid claiming unfinished work is done.",...lines.length>0?["Current Navigator Todo items:",...lines]:[]].join(`
|
|
11
|
+
`)
|
|
12
|
+
}
|
|
13
|
+
function key(sessionID){return `session.todo.${sessionID}`
|
|
14
|
+
}
|
|
15
|
+
function createManagedTodos(storage,onChange){const pending=new Map
|
|
16
|
+
async function list(sessionID){return normalizeTodoState(await storage.get(key(sessionID)))
|
|
17
|
+
}
|
|
18
|
+
function change(sessionID,apply){const request=(pending.get(sessionID)??Promise.resolve()).catch(()=>{}).then(async ()=>{const next=apply(await list(sessionID))
|
|
19
|
+
await storage.set(key(sessionID),next)
|
|
20
|
+
await onChange(sessionID,next)
|
|
21
|
+
return next
|
|
22
|
+
})
|
|
23
|
+
pending.set(sessionID,request)
|
|
24
|
+
const clear=()=>{if(pending.get(sessionID)===request)
|
|
25
|
+
pending.delete(sessionID)
|
|
26
|
+
}
|
|
27
|
+
request.then(clear).catch(clear)
|
|
28
|
+
return request
|
|
29
|
+
}
|
|
30
|
+
return{list,replace(sessionID,todos){return change(sessionID,(current)=>({...current,todos:normalizeTodoState({todos}).todos}))
|
|
31
|
+
},guidance(sessionID,enabled){return change(sessionID,(current)=>({...current,guidance:enabled}))
|
|
32
|
+
}}}
|
|
33
|
+
var item={type:"object",properties:{content:{type:"string",minLength:1,maxLength:512},status:{type:"string",enum:["pending","in_progress","completed","cancelled"]},priority:{type:"string",enum:["high","medium","low"]}},required:["content","status"],additionalProperties:false
|
|
34
|
+
}
|
|
35
|
+
var todos={type:"array",items:item,maxItems:100}
|
|
36
|
+
var sessionID={type:"string",minLength:1}
|
|
37
|
+
var output={type:"object",properties:{todos,guidance:{type:"boolean"}},required:["todos","guidance"],additionalProperties:false
|
|
38
|
+
}
|
|
39
|
+
var NavigatorTodoRpc={id:"opencode-navigator.todo",methods:{list:{input:{type:"object",properties:{sessionID},required:["sessionID"],additionalProperties:false},output
|
|
40
|
+
},replace:{input:{type:"object",properties:{sessionID,todos},required:["sessionID","todos"],additionalProperties:false
|
|
41
|
+
},output
|
|
42
|
+
},guidance:{input:{type:"object",properties:{sessionID,enabled:{type:"boolean"}},required:["sessionID","enabled"],additionalProperties:false
|
|
43
|
+
},output
|
|
44
|
+
}},events:{updated:{schema:{type:"object",properties:{sessionID,todos,guidance:{type:"boolean"}},required:["sessionID","todos","guidance"],additionalProperties:false
|
|
45
|
+
}}}};
|
|
46
|
+
var input={type:"object",properties:{todos:NavigatorTodoRpc.methods.replace.input.properties.todos
|
|
47
|
+
},required:["todos"],additionalProperties:false
|
|
48
|
+
}
|
|
49
|
+
var noNotify=async ()=>{}
|
|
50
|
+
var todo_server_default=Plugin.define({id:"opencode-navigator.todo-server",async setup(host){let notify=noNotify
|
|
51
|
+
const todos=createManagedTodos({get:(key)=>host.storage.get(key),set:(key,value)=>host.storage.set(key,value)
|
|
52
|
+
},(sessionID,state)=>notify(sessionID,state))
|
|
53
|
+
const rpc=await host.rpc.register(NavigatorTodoRpc,{list:async (value)=>todos.list(value.sessionID),replace:async (value)=>{const{sessionID,todos:items}=value
|
|
54
|
+
return todos.replace(sessionID,items)
|
|
55
|
+
},guidance:async (value)=>{const{sessionID,enabled}=value
|
|
56
|
+
return todos.guidance(sessionID,enabled)
|
|
57
|
+
}})
|
|
58
|
+
notify=(sessionID,state)=>rpc.events.emit("updated",{sessionID,...state})
|
|
59
|
+
const tools=await host.tool.transform((editor)=>{editor.namespace({name:"navigator",description:"Navigator session tasks"})
|
|
60
|
+
editor.add({name:"todo_write",description:"Replace the Navigator Todo list for this session with the current tasks and their statuses.",input,options:{namespace:"navigator"},execute:async (value,context)=>{const state=await todos.replace(context.sessionID,value.todos)
|
|
61
|
+
return{content:`Navigator Todo updated: ${state.todos.length} tasks.`}}})
|
|
62
|
+
})
|
|
63
|
+
const context=await host.session.hook("context",async (event)=>{const state=await todos.list(event.sessionID)
|
|
64
|
+
if(state.guidance)
|
|
65
|
+
event.system.push({type:"text",text:todoGuidance(state)})
|
|
66
|
+
})
|
|
67
|
+
return async ()=>{await context.dispose()
|
|
68
|
+
await tools.dispose()
|
|
69
|
+
await rpc.dispose()
|
|
70
|
+
}}})
|
|
71
|
+
export{todo_server_default as default
|
|
72
|
+
}
|
package/dist/tui.js
CHANGED
|
@@ -2,7 +2,7 @@ import {insert as _$insert,setProp as _$setProp,createElement as _$createElement
|
|
|
2
2
|
|
|
3
3
|
|
|
4
4
|
|
|
5
|
-
import {createSignal as createSignal2,createSignal,createEffect,onCleanup,createContext,useContext,createContext as createContext2,createSignal as createSignal3,useContext as useContext2,createEffect as createEffect2,splitProps,untrack,splitProps as splitProps2,For,createEffect as createEffect3,onCleanup as onCleanup2,Show,splitProps as splitProps3,createSignal as createSignal4,createSignal as createSignal5,createSignal as createSignal6,onCleanup as onCleanup3,batch,createSignal as createSignal8,createSignal as createSignal7,createEffect as createEffect4,createSignal as createSignal9,onCleanup as onCleanup4,createSignal as createSignal10,Index,createSignal as
|
|
5
|
+
import {createSignal as createSignal2,createSignal,createEffect,onCleanup,createContext,useContext,createContext as createContext2,createSignal as createSignal3,useContext as useContext2,createEffect as createEffect2,splitProps,untrack,splitProps as splitProps2,For,createEffect as createEffect3,onCleanup as onCleanup2,Show,splitProps as splitProps3,createSignal as createSignal4,createSignal as createSignal5,createSignal as createSignal6,onCleanup as onCleanup3,batch,createSignal as createSignal8,createSignal as createSignal7,createEffect as createEffect4,createSignal as createSignal9,onCleanup as onCleanup4,createSignal as createSignal10,createSignal as createSignal11,Index,createSignal as createSignal12,onCleanup as onCleanup5,createEffect as createEffect6,onCleanup as onCleanup7,batch as batch2,createEffect as createEffect5,createMemo,createSignal as createSignal13,onCleanup as onCleanup6,onMount,For as For2,For as For3,Show as Show2,createMemo as createMemo2,Show as Show3,createSignal as createSignal14,onCleanup as onCleanup8,For as For4,For as For5,For as For8,createMemo as createMemo4,onMount as onMount3,For as For7,createMemo as createMemo3,onMount as onMount2,Show as Show5,createEffect as createEffect7,createSignal as createSignal15,onCleanup as onCleanup9,Show as Show4,For as For6,For as For9,createEffect as createEffect8,createMemo as createMemo5,onCleanup as onCleanup10,For as For10,createEffect as createEffect9,createMemo as createMemo8,onCleanup as onCleanup11,onMount as onMount4,createMemo as createMemo6,createMemo as createMemo7,Show as Show6,onCleanup as onCleanup12,createSignal as createSignal16,createEffect as createEffect10,onCleanup as onCleanup13,onMount as onMount5,onCleanup as onCleanup14,onMount as onMount6,For as For11,createSignal as createSignal17,createSignal as createSignal18,Show as Show7,createSignal as createSignal20,createSignal as createSignal19,onCleanup as onCleanup15,For as For12,Show as Show10,createMemo as createMemo10,createComputed,createMemo as createMemo9,createSignal as createSignal21,untrack as untrack2,Show as Show8,createComputed as createComputed2,untrack as untrack3,Show as Show9,createEffect as createEffect11,createSignal as createSignal22,createMemo as createMemo12,createSignal as createSignal24,createMemo as createMemo11,For as For13,Show as Show13,Show as Show11,Show as Show12,createSignal as createSignal23,onCleanup as onCleanup16,For as For14,Show as Show15,createMemo as createMemo14,Show as Show14,createMemo as createMemo13,createEffect as createEffect12,onCleanup as onCleanup17,For as For19,Match,Switch,createMemo as createMemo18,onCleanup as onCleanup21,For as For15,Show as Show16,createSignal as createSignal25,createEffect as createEffect13,createMemo as createMemo15,onCleanup as onCleanup18,untrack as untrack4,For as For17,Show as Show19,createEffect as createEffect14,createMemo as createMemo16,createSignal as createSignal26,onCleanup as onCleanup19,untrack as untrack5,For as For16,Show as Show18,Show as Show17,Show as Show23,createEffect as createEffect15,createMemo as createMemo17,createSignal as createSignal27,onCleanup as onCleanup20,untrack as untrack6,For as For18,Show as Show21,Show as Show20,Show as Show22,createEffect as createEffect16,createMemo as createMemo19,onCleanup as onCleanup22,untrack as untrack7,Show as Show24,createMemo as createMemo20,onCleanup as onCleanup23,createSignal as createSignal28,onCleanup as onCleanup24,onMount as onMount7} from "solid-js"
|
|
6
6
|
var SIDEBAR_SECTIONS=["todo","subagents","skills","quick_actions","lsp","mcp"]
|
|
7
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"]
|
|
8
8
|
function preferencesScope(path){return path.worktree||path.directory||"global"
|
|
@@ -2619,6 +2619,99 @@ activeTarget=undefined
|
|
|
2619
2619
|
requests.abortAll()
|
|
2620
2620
|
refreshing.clear()
|
|
2621
2621
|
}}}}
|
|
2622
|
+
function normalizeTodoState(value){if(!value||typeof value!=="object")
|
|
2623
|
+
return{todos:[],guidance:false}
|
|
2624
|
+
const state=value
|
|
2625
|
+
const statuses=new Set(["pending","in_progress","completed","cancelled"])
|
|
2626
|
+
const priorities=new Set(["high","medium","low"])
|
|
2627
|
+
const todos=Array.isArray(state.todos)?state.todos.filter((item)=>item&&typeof item.content==="string"&&item.content.trim().length>0&&item.content.length<=512&&statuses.has(item.status)).slice(0,100).map((item)=>({content:item.content.trim(),status:item.status,...priorities.has(item.priority??"")&&{priority:item.priority}})):[]
|
|
2628
|
+
return{todos,guidance:state.guidance===true}}
|
|
2629
|
+
|
|
2630
|
+
var item={type:"object",properties:{content:{type:"string",minLength:1,maxLength:512},status:{type:"string",enum:["pending","in_progress","completed","cancelled"]},priority:{type:"string",enum:["high","medium","low"]}},required:["content","status"],additionalProperties:false
|
|
2631
|
+
}
|
|
2632
|
+
var todos={type:"array",items:item,maxItems:100}
|
|
2633
|
+
var sessionID={type:"string",minLength:1}
|
|
2634
|
+
var output={type:"object",properties:{todos,guidance:{type:"boolean"}},required:["todos","guidance"],additionalProperties:false
|
|
2635
|
+
}
|
|
2636
|
+
var NavigatorTodoRpc={id:"opencode-navigator.todo",methods:{list:{input:{type:"object",properties:{sessionID},required:["sessionID"],additionalProperties:false},output
|
|
2637
|
+
},replace:{input:{type:"object",properties:{sessionID,todos},required:["sessionID","todos"],additionalProperties:false
|
|
2638
|
+
},output
|
|
2639
|
+
},guidance:{input:{type:"object",properties:{sessionID,enabled:{type:"boolean"}},required:["sessionID","enabled"],additionalProperties:false
|
|
2640
|
+
},output
|
|
2641
|
+
}},events:{updated:{schema:{type:"object",properties:{sessionID,todos,guidance:{type:"boolean"}},required:["sessionID","todos","guidance"],additionalProperties:false
|
|
2642
|
+
}}}};
|
|
2643
|
+
function createNavigatorTodoController(context,api){const rpc=context.client.rpc(NavigatorTodoRpc)
|
|
2644
|
+
const [sessions,setSessions]=createSignal11({})
|
|
2645
|
+
const [saving,setSaving]=createSignal11({})
|
|
2646
|
+
const [errors,setErrors]=createSignal11({})
|
|
2647
|
+
const requests=createRequestState(api.lifecycle.signal)
|
|
2648
|
+
const refreshing=new Map
|
|
2649
|
+
const revisions=new Map
|
|
2650
|
+
let activeTarget
|
|
2651
|
+
function target(sessionID){const session=api.state.session.get(sessionID)
|
|
2652
|
+
const directory=session?.directory??api.state.path.directory
|
|
2653
|
+
const workspace=session?.workspaceID
|
|
2654
|
+
return{key:JSON.stringify([sessionID,directory,workspace??null]),sessionID,routing:{directory}}}
|
|
2655
|
+
function set(key,value){setSessions((current)=>({...current,[key]:normalizeTodoState(value)}))
|
|
2656
|
+
}
|
|
2657
|
+
function refresh(sessionID,force=false){const current=target(sessionID)
|
|
2658
|
+
const pending=refreshing.get(current.key)
|
|
2659
|
+
if(pending&&!force)
|
|
2660
|
+
return pending
|
|
2661
|
+
const revision=revisions.get(current.key)??0
|
|
2662
|
+
const requestState=requests.start(current.key,"refresh Navigator todos",current.key in sessions(),force)
|
|
2663
|
+
if(!requestState)
|
|
2664
|
+
return pending
|
|
2665
|
+
const request=rpc.list({sessionID},{location:current.routing,signal:requestState.signal}).then((value)=>{const state=normalizeTodoState(value)
|
|
2666
|
+
if(requestState.isCurrent()&&(revisions.get(current.key)??0)===revision)
|
|
2667
|
+
set(current.key,state)
|
|
2668
|
+
requestState.succeed()
|
|
2669
|
+
return state
|
|
2670
|
+
}).catch((error)=>{requestState.fail(error)
|
|
2671
|
+
throw error
|
|
2672
|
+
}).finally(()=>{requestState.finish()
|
|
2673
|
+
if(refreshing.get(current.key)===request)
|
|
2674
|
+
refreshing.delete(current.key)
|
|
2675
|
+
})
|
|
2676
|
+
refreshing.set(current.key,request)
|
|
2677
|
+
return request
|
|
2678
|
+
}
|
|
2679
|
+
const unsubscribe=rpc.events.on("updated",(event)=>{const{sessionID}=event.data
|
|
2680
|
+
if(typeof sessionID!=="string")
|
|
2681
|
+
return
|
|
2682
|
+
const current=target(sessionID)
|
|
2683
|
+
if(event.location.directory!==current.routing.directory)
|
|
2684
|
+
return
|
|
2685
|
+
revisions.set(current.key,(revisions.get(current.key)??0) + 1)
|
|
2686
|
+
set(current.key,normalizeTodoState(event.data))
|
|
2687
|
+
})
|
|
2688
|
+
api.lifecycle.onDispose(unsubscribe)
|
|
2689
|
+
return{target,list(sessionID){return sessions()[target(sessionID).key]?.todos??[]
|
|
2690
|
+
},refresh,state(sessionID){return requests.state(target(sessionID).key)
|
|
2691
|
+
},retry(sessionID){return refresh(sessionID,true)
|
|
2692
|
+
},guidance(sessionID){const key=target(sessionID).key
|
|
2693
|
+
return{enabled:sessions()[key]?.guidance??false,saving:saving()[key]??false,error:errors()[key],available:key in sessions()
|
|
2694
|
+
}},async setGuidance(sessionID,enabled){const current=target(sessionID)
|
|
2695
|
+
if(!(current.key in sessions())||saving()[current.key])
|
|
2696
|
+
return
|
|
2697
|
+
setSaving((value)=>({...value,[current.key]:true}))
|
|
2698
|
+
setErrors((value)=>({...value,[current.key]:undefined}))
|
|
2699
|
+
try{const state=await rpc.guidance({sessionID,enabled},{location:current.routing})
|
|
2700
|
+
revisions.set(current.key,(revisions.get(current.key)??0) + 1)
|
|
2701
|
+
set(current.key,normalizeTodoState(state))
|
|
2702
|
+
} catch(error){setErrors((value)=>({...value,[current.key]:error instanceof Error?error.message:String(error)}))
|
|
2703
|
+
} finally{setSaving((value)=>({...value,[current.key]:false}))
|
|
2704
|
+
}},activate(sessionID){const key=target(sessionID).key
|
|
2705
|
+
if(activeTarget!==key){requests.abortAll()
|
|
2706
|
+
refreshing.clear()
|
|
2707
|
+
activeTarget=key
|
|
2708
|
+
}
|
|
2709
|
+
return()=>{if(activeTarget!==key)
|
|
2710
|
+
return
|
|
2711
|
+
activeTarget=undefined
|
|
2712
|
+
requests.abortAll()
|
|
2713
|
+
refreshing.clear()
|
|
2714
|
+
}}}}
|
|
2622
2715
|
function buildTodoView(todos,mode){const active=[...todos.filter((item)=>item.status==="in_progress"),...todos.filter((item)=>item.status==="pending")]
|
|
2623
2716
|
const completed=todos.filter((item)=>item.status==="completed")
|
|
2624
2717
|
const cancelled=todos.filter((item)=>item.status==="cancelled")
|
|
@@ -2673,7 +2766,7 @@ return action.label
|
|
|
2673
2766
|
const command=api.keymap.getCommands?.({visibility:"registered"}).find((candidate)=>candidate.name===action.command)
|
|
2674
2767
|
return typeof command?.title==="string"?command.title:action.label
|
|
2675
2768
|
}
|
|
2676
|
-
function createQuickActionRevision(api){const [revision,setRevision]=
|
|
2769
|
+
function createQuickActionRevision(api){const [revision,setRevision]=createSignal12(0)
|
|
2677
2770
|
const unsubscribe=api.keymap.on?.("state",()=>setRevision((value)=>value + 1))
|
|
2678
2771
|
if(unsubscribe)
|
|
2679
2772
|
onCleanup5(unsubscribe)
|
|
@@ -2771,7 +2864,7 @@ const [selectedID,setSelectedID]=useDialogState("selection",undefined)
|
|
|
2771
2864
|
const [views]=useDialogState("tab-views",new Map)
|
|
2772
2865
|
const tabViews=views()
|
|
2773
2866
|
const [scrollTop,setScrollTop]=useDialogState("scroll",0)
|
|
2774
|
-
const [refreshing,setRefreshing]=
|
|
2867
|
+
const [refreshing,setRefreshing]=createSignal13(false)
|
|
2775
2868
|
const theme=()=>props.api.theme.current
|
|
2776
2869
|
const icons=useIcons()
|
|
2777
2870
|
const commandRevision=createQuickActionRevision(props.api)
|
|
@@ -3397,8 +3490,8 @@ return _el$
|
|
|
3397
3490
|
}
|
|
3398
3491
|
function FirstRunWizard(props){const icons=useIcons()
|
|
3399
3492
|
const dialogs=useDialogs(props.api)
|
|
3400
|
-
const [active,setActive]=
|
|
3401
|
-
const [step,setStep]=
|
|
3493
|
+
const [active,setActive]=createSignal14(0)
|
|
3494
|
+
const [step,setStep]=createSignal14(0)
|
|
3402
3495
|
const theme=()=>props.api.theme.current
|
|
3403
3496
|
const sections=SECTION_DEFINITIONS.filter((section)=>supportsSidebarSection(props.api,section.name))
|
|
3404
3497
|
const finishIndex=sections.length
|
|
@@ -3586,7 +3679,7 @@ const dialogs=useDialogs(props.api)
|
|
|
3586
3679
|
const theme=()=>props.api.theme.current
|
|
3587
3680
|
const dimensions=useTerminalDimensions4()
|
|
3588
3681
|
const scroll=useDialogScroll()
|
|
3589
|
-
const [active,setActive]=
|
|
3682
|
+
const [active,setActive]=createSignal15("apply")
|
|
3590
3683
|
let body
|
|
3591
3684
|
const prefix=`${PLUGIN_ID}.preset-preview`
|
|
3592
3685
|
function activate(action){if(!props.valid()){dialogs.close()
|
|
@@ -4628,7 +4721,7 @@ return _$createElement("box")
|
|
|
4628
4721
|
|
|
4629
4722
|
|
|
4630
4723
|
function SettingsFooterButton(props){const icons=useIcons()
|
|
4631
|
-
const [hovered,setHovered]=
|
|
4724
|
+
const [hovered,setHovered]=createSignal16(false)
|
|
4632
4725
|
const theme=()=>props.api.theme.current
|
|
4633
4726
|
return _$createComponent(IconControl,{id:`${PLUGIN_ID}.settings.footer`,get icon(){return icons.icon("settings")
|
|
4634
4727
|
},get foregroundColor(){return _$memo(()=>!!hovered())()?theme().text:theme().textMuted
|
|
@@ -4849,8 +4942,8 @@ return _$createElement("box")
|
|
|
4849
4942
|
|
|
4850
4943
|
var NAVIGATOR_PACKAGE_URL="https://registry.npmjs.org/opencode-navigator/latest"
|
|
4851
4944
|
var REQUEST_TIMEOUT_MS=5000
|
|
4852
|
-
function createVersionStatus(api,navigatorVersion,request=fetch){const [openCodeUpdate,setOpenCodeUpdate]=
|
|
4853
|
-
const [navigatorUpdate,setNavigatorUpdate]=
|
|
4945
|
+
function createVersionStatus(api,navigatorVersion,request=fetch){const [openCodeUpdate,setOpenCodeUpdate]=createSignal17()
|
|
4946
|
+
const [navigatorUpdate,setNavigatorUpdate]=createSignal17()
|
|
4854
4947
|
const controller=new AbortController
|
|
4855
4948
|
const timeout=setTimeout(()=>controller.abort(),REQUEST_TIMEOUT_MS)
|
|
4856
4949
|
const unsubscribe=api.event.on("installation.update-available",(event)=>{const version=event.properties.version
|
|
@@ -5013,9 +5106,9 @@ return false
|
|
|
5013
5106
|
return true
|
|
5014
5107
|
}
|
|
5015
5108
|
function createSidebarInteraction(api,showHelp=()=>openKeyboardHelp(api)){const descriptors=new Map
|
|
5016
|
-
const [selectedId,setSelectedId]=
|
|
5017
|
-
const [focusWithin,setFocusWithin]=
|
|
5018
|
-
const [revision,setRevision]=
|
|
5109
|
+
const [selectedId,setSelectedId]=createSignal18()
|
|
5110
|
+
const [focusWithin,setFocusWithin]=createSignal18(false)
|
|
5111
|
+
const [revision,setRevision]=createSignal18(0)
|
|
5019
5112
|
let titleRoot
|
|
5020
5113
|
let contentRoot
|
|
5021
5114
|
let targetedRoot
|
|
@@ -5284,7 +5377,7 @@ else if(highlighted)
|
|
|
5284
5377
|
foregroundColor=theme.selectedListItemText
|
|
5285
5378
|
return{backgroundColor,foregroundColor}}
|
|
5286
5379
|
function useSidebarItem(api,interaction,descriptor,normalColor=()=>api.theme.current.text,mode="row"){let unregister
|
|
5287
|
-
const [hovered,setHovered]=
|
|
5380
|
+
const [hovered,setHovered]=createSignal19(false)
|
|
5288
5381
|
const disabled=()=>descriptor.disabled?.()===true
|
|
5289
5382
|
const focused=()=>Boolean(interaction?.ownsFocus()&&interaction.isSelected(descriptor.id))
|
|
5290
5383
|
const colors=()=>sidebarInteractiveColors(api.theme.current,{focused:focused(),hovered:hovered(),disabled:disabled()},normalColor(),mode)
|
|
@@ -5302,7 +5395,7 @@ return true
|
|
|
5302
5395
|
}}}
|
|
5303
5396
|
function LspBadge(props){const icons=useIcons()
|
|
5304
5397
|
const isKnown=lspIconName(props.id)!==undefined
|
|
5305
|
-
const [showName,setShowName]=
|
|
5398
|
+
const [showName,setShowName]=createSignal20(false)
|
|
5306
5399
|
const statusColor=()=>props.status==="connected"?props.api.theme.current.success:props.api.theme.current.error
|
|
5307
5400
|
if(!isKnown){return(()=>{var _el$=_$createElement("text")
|
|
5308
5401
|
_$setProp(_el$,"flexShrink",1)
|
|
@@ -5345,7 +5438,7 @@ return _el$3
|
|
|
5345
5438
|
|
|
5346
5439
|
|
|
5347
5440
|
|
|
5348
|
-
function createListVisibility(options){const [expanded,setExpanded]=
|
|
5441
|
+
function createListVisibility(options){const [expanded,setExpanded]=createSignal21(false)
|
|
5349
5442
|
let previousKey
|
|
5350
5443
|
let previousLimit
|
|
5351
5444
|
const canToggle=createMemo9(()=>options.limit()>0&&options.items().length>options.limit())
|
|
@@ -5427,7 +5520,7 @@ result += segment
|
|
|
5427
5520
|
return result + ellipsis
|
|
5428
5521
|
}
|
|
5429
5522
|
function Section(props){const icons=useIcons()
|
|
5430
|
-
const [actionWidth,setActionWidth]=
|
|
5523
|
+
const [actionWidth,setActionWidth]=createSignal22()
|
|
5431
5524
|
const icon=()=>props.section?icons.section(props.section):props.icon
|
|
5432
5525
|
const theme=()=>props.api.theme.current
|
|
5433
5526
|
const item=useSidebarItem(props.api,props.interaction,{id:props.sectionId??`section.${props.title}`,position:()=>({section:props.navigationSection??0,row:0,column:0
|
|
@@ -5778,7 +5871,7 @@ return _el$2
|
|
|
5778
5871
|
function SectionFilter(props){const icons=useIcons()
|
|
5779
5872
|
let input
|
|
5780
5873
|
let unregisterInput
|
|
5781
|
-
const [inputFocused,setInputFocused]=
|
|
5874
|
+
const [inputFocused,setInputFocused]=createSignal23(false)
|
|
5782
5875
|
const theme=()=>props.api.theme.current
|
|
5783
5876
|
const item=useSidebarItem(props.api,props.interaction,{id:props.id??`filter.${props.placeholder}`,position:()=>props.position??{section:0,row:0,column:0
|
|
5784
5877
|
},activate:()=>{if(!input)
|
|
@@ -5953,7 +6046,7 @@ return _el$
|
|
|
5953
6046
|
}})
|
|
5954
6047
|
}
|
|
5955
6048
|
function McpSection(props){const icons=useIcons()
|
|
5956
|
-
const [query,setQuery]=
|
|
6049
|
+
const [query,setQuery]=createSignal24("")
|
|
5957
6050
|
const model=createMcpSectionModel(props,query)
|
|
5958
6051
|
const navigationSection=()=>props.navigationSection??6
|
|
5959
6052
|
const summary=createMemo12(()=>`${model.active()}/${model.list().length}${model.errors() ? ` \xB7 ${model.errors()} ${icons.icon("error")}` : ""}`)
|
|
@@ -6299,7 +6392,7 @@ return _el$2
|
|
|
6299
6392
|
}})
|
|
6300
6393
|
}
|
|
6301
6394
|
function SkillsSection(props){const dialogs=useDialogs(props.api)
|
|
6302
|
-
const [query,setQuery]=
|
|
6395
|
+
const [query,setQuery]=createSignal25("")
|
|
6303
6396
|
const model=createSkillSectionModel(props,query)
|
|
6304
6397
|
const navigationSection=()=>props.navigationSection??3
|
|
6305
6398
|
function selectSkill(item){if(!props.preferences.shouldConfirmSkill(item)){model.useSkill(item)
|
|
@@ -6374,8 +6467,8 @@ return _el$
|
|
|
6374
6467
|
function createSubagentSectionModel(props){const list=createMemo16(()=>props.controller.list(props.sessionID))
|
|
6375
6468
|
const recent=createMemo16(()=>props.controller.recent?.(props.sessionID)??[])
|
|
6376
6469
|
const rows=createMemo16(()=>buildSubagentView(list(),recent()))
|
|
6377
|
-
const [query,setQuery]=
|
|
6378
|
-
const [mode,setMode]=
|
|
6470
|
+
const [query,setQuery]=createSignal26("")
|
|
6471
|
+
const [mode,setMode]=createSignal26("all")
|
|
6379
6472
|
const counts=createMemo16(()=>countSubagentView(rows(),query()))
|
|
6380
6473
|
const tabs=createMemo16(()=>["all","active","recent",...counts().errors>0?["errors"]:[]])
|
|
6381
6474
|
const filtered=createMemo16(()=>filterSubagentView(rows(),mode(),query()))
|
|
@@ -6657,6 +6750,7 @@ return _el$
|
|
|
6657
6750
|
})()
|
|
6658
6751
|
}
|
|
6659
6752
|
function TodoContents(props){const navigationSection=()=>props.navigationSection??1
|
|
6753
|
+
const tabsRow=()=>props.managed?3:2
|
|
6660
6754
|
return(()=>{var _el$=_$createElement("box"),_el$2=_$createElement("box")
|
|
6661
6755
|
_$insertNode(_el$,_el$2)
|
|
6662
6756
|
_$setProp(_el$,"gap",1)
|
|
@@ -6664,7 +6758,7 @@ _$setProp(_el$2,"flexDirection","row")
|
|
|
6664
6758
|
_$setProp(_el$2,"flexWrap","wrap")
|
|
6665
6759
|
_$insert(_el$2,_$createComponent(For18,{each:["all","active","finished"],children:(value,index)=>_$createComponent(SectionTab,{get api(){return props.api
|
|
6666
6760
|
},get interaction(){return props.interaction
|
|
6667
|
-
},id:`${PLUGIN_ID}.todo.filter.${value}`,get position(){return{section:navigationSection(),row:
|
|
6761
|
+
},id:`${PLUGIN_ID}.todo.filter.${value}`,get position(){return{section:navigationSection(),row:tabsRow(),column:index()
|
|
6668
6762
|
}},get label(){return value[0].toUpperCase() + value.slice(1)
|
|
6669
6763
|
},get count(){return props.view.counts[value]
|
|
6670
6764
|
},get selected(){return props.mode===value
|
|
@@ -6698,7 +6792,8 @@ return _el$3
|
|
|
6698
6792
|
_$insert(_el$,_$createComponent(ListVisibilityControl,{get api(){return props.api
|
|
6699
6793
|
},get interaction(){return props.interaction
|
|
6700
6794
|
},section:"todo",get navigationSection(){return navigationSection()
|
|
6701
|
-
},
|
|
6795
|
+
},get row(){return tabsRow() + 1
|
|
6796
|
+
},get visibility(){return props.visibility
|
|
6702
6797
|
}}),null)
|
|
6703
6798
|
return _el$
|
|
6704
6799
|
})()
|
|
@@ -6709,10 +6804,39 @@ _$effect((_$p)=>_$setProp(_el$6,"fg",props.api.theme.current.textMuted,_$p))
|
|
|
6709
6804
|
return _el$6
|
|
6710
6805
|
})()
|
|
6711
6806
|
}
|
|
6807
|
+
|
|
6808
|
+
|
|
6809
|
+
|
|
6810
|
+
|
|
6811
|
+
|
|
6812
|
+
|
|
6813
|
+
function TodoGuidanceControl(props){const state=()=>props.controller.guidance(props.sessionID)
|
|
6814
|
+
return _$createComponent(Show22,{get when(){return state().available
|
|
6815
|
+
},get children(){var _el$=_$createElement("box")
|
|
6816
|
+
_$insert(_el$,_$createComponent(SectionTab,{get api(){return props.api
|
|
6817
|
+
},get interaction(){return props.interaction
|
|
6818
|
+
},id:`${PLUGIN_ID}.todo.guidance`,get position(){return{section:props.navigationSection,row:2,column:0
|
|
6819
|
+
}},get label(){return `Todo instructions: ${state().enabled ? "On" : "Off"}`
|
|
6820
|
+
},get selected(){return state().enabled
|
|
6821
|
+
},get disabled(){return state().saving
|
|
6822
|
+
},onActivate:()=>void props.controller.setGuidance(props.sessionID,!state().enabled)
|
|
6823
|
+
}),null)
|
|
6824
|
+
_$insert(_el$,_$createComponent(Show22,{get when(){return state().error
|
|
6825
|
+
},children:(message)=>(()=>{var _el$2=_$createElement("text")
|
|
6826
|
+
_$setProp(_el$2,"wrapMode","word")
|
|
6827
|
+
_$insert(_el$2,message)
|
|
6828
|
+
_$effect((_$p)=>_$setProp(_el$2,"fg",props.api.theme.current.error,_$p))
|
|
6829
|
+
return _el$2
|
|
6830
|
+
})()
|
|
6831
|
+
}),null)
|
|
6832
|
+
return _el$
|
|
6833
|
+
}})
|
|
6834
|
+
}
|
|
6712
6835
|
function TodoSection(props){const list=createMemo17(()=>props.controller.list(props.sessionID))
|
|
6713
6836
|
const icons=useIcons()
|
|
6714
6837
|
const unavailable=()=>hostCapabilityUnavailable(props.api,"todo")
|
|
6715
|
-
const
|
|
6838
|
+
const managed=()=>("guidance" in props.controller)?props.controller:undefined
|
|
6839
|
+
const [mode,setMode]=createSignal27("all")
|
|
6716
6840
|
const targetKey=createMemo17(()=>props.controller.target?.(props.sessionID).key??props.sessionID)
|
|
6717
6841
|
createEffect15(()=>{targetKey()
|
|
6718
6842
|
setMode("all")
|
|
@@ -6735,28 +6859,48 @@ return _$createComponent(Section,{get api(){return props.api
|
|
|
6735
6859
|
},sectionId:`${PLUGIN_ID}.section.todo`,get navigationSection(){return navigationSection()
|
|
6736
6860
|
},title:"TODO",section:"todo",get summary(){return _$memo(()=>!!unavailable())()?"\u2014":`${view().counts.completed}/${list().length}`
|
|
6737
6861
|
},get open(){return props.preferences.expanded().todo
|
|
6738
|
-
},onToggle:()=>props.preferences.toggleSectionExpanded("todo"),get children(){return _$createComponent(
|
|
6739
|
-
},get fallback(){return _$
|
|
6862
|
+
},onToggle:()=>props.preferences.toggleSectionExpanded("todo"),get children(){return _$createComponent(Show23,{get when(){return unavailable()
|
|
6863
|
+
},get fallback(){return(()=>{var _el$=_$createElement("box")
|
|
6864
|
+
_$setProp(_el$,"gap",1)
|
|
6865
|
+
_$insert(_el$,_$createComponent(Show23,{get when(){return managed()?.guidance(props.sessionID).available
|
|
6866
|
+
},get children(){return _$createComponent(TodoGuidanceControl,{get api(){return props.api
|
|
6867
|
+
},get controller(){return managed()
|
|
6868
|
+
},get sessionID(){return props.sessionID
|
|
6869
|
+
},get interaction(){return props.interaction
|
|
6870
|
+
},get navigationSection(){return navigationSection()
|
|
6871
|
+
}})
|
|
6872
|
+
}}),null)
|
|
6873
|
+
_$insert(_el$,_$createComponent(Show23,{get when(){return _$memo(()=>!!(managed()&&state().error))()&&!managed()?.guidance(props.sessionID).available
|
|
6874
|
+
},get children(){var _el$2=_$createElement("text")
|
|
6875
|
+
_$insertNode(_el$2,_$createTextNode(`Add Navigator's server plugin to opencode.json; restart OpenCode to enable Todo.`))
|
|
6876
|
+
_$setProp(_el$2,"wrapMode","word")
|
|
6877
|
+
_$effect((_$p)=>_$setProp(_el$2,"fg",props.api.theme.current.textMuted,_$p))
|
|
6878
|
+
return _el$2
|
|
6879
|
+
}}),null)
|
|
6880
|
+
_$insert(_el$,_$createComponent(SectionRequestBody,{get api(){return props.api
|
|
6740
6881
|
},get interaction(){return props.interaction
|
|
6741
6882
|
},id:`${PLUGIN_ID}.retry.todo`,get position(){return{section:navigationSection(),row:1,column:0
|
|
6742
6883
|
}},get state(){return state()
|
|
6743
6884
|
},get hasItems(){return list().length>0
|
|
6744
|
-
},empty:"No tasks yet",loading:"Loading tasks\u2026",onRetry:()=>void props.controller.retry(props.sessionID),get children(){return _$createComponent(TodoContents,{get api(){return props.api
|
|
6885
|
+
},empty:"No tasks yet",loading:"Loading tasks\u2026",onRetry:()=>void props.controller.retry(props.sessionID).catch(()=>{}),get children(){return _$createComponent(TodoContents,{get api(){return props.api
|
|
6745
6886
|
},get interaction(){return props.interaction
|
|
6746
6887
|
},get navigationSection(){return props.navigationSection
|
|
6747
6888
|
},get mode(){return mode()
|
|
6748
6889
|
},setMode,get view(){return view()
|
|
6749
6890
|
},visibility,get density(){return props.preferences.rowDensity?.()??"compact"
|
|
6891
|
+
},get managed(){return Boolean(managed())
|
|
6750
6892
|
}})
|
|
6751
|
-
}})
|
|
6752
|
-
},children:(message)=>(()=>{var _el$=_$createElement("text"),_el$2=_$createTextNode(` `)
|
|
6753
|
-
_$insertNode(_el$,_el$2)
|
|
6754
|
-
_$setProp(_el$,"wrapMode","word")
|
|
6755
|
-
_$insert(_el$,()=>icons.icon("info"),_el$2)
|
|
6756
|
-
_$insert(_el$,message,null)
|
|
6757
|
-
_$effect((_$p)=>_$setProp(_el$,"fg",props.api.theme.current.textMuted,_$p))
|
|
6893
|
+
}}),null)
|
|
6758
6894
|
return _el$
|
|
6759
6895
|
})()
|
|
6896
|
+
},children:(message)=>(()=>{var _el$4=_$createElement("text"),_el$5=_$createTextNode(` `)
|
|
6897
|
+
_$insertNode(_el$4,_el$5)
|
|
6898
|
+
_$setProp(_el$4,"wrapMode","word")
|
|
6899
|
+
_$insert(_el$4,()=>icons.icon("info"),_el$5)
|
|
6900
|
+
_$insert(_el$4,message,null)
|
|
6901
|
+
_$effect((_$p)=>_$setProp(_el$4,"fg",props.api.theme.current.textMuted,_$p))
|
|
6902
|
+
return _el$4
|
|
6903
|
+
})()
|
|
6760
6904
|
})
|
|
6761
6905
|
}})
|
|
6762
6906
|
}
|
|
@@ -6868,7 +7012,7 @@ _$setProp(_el$2,"flexDirection","row")
|
|
|
6868
7012
|
_$setProp(_el$2,"justifyContent","space-between")
|
|
6869
7013
|
_$setProp(_el$2,"gap",1)
|
|
6870
7014
|
_$setProp(_el$3,"flexGrow",1)
|
|
6871
|
-
_$insert(_el$3,_$createComponent(
|
|
7015
|
+
_$insert(_el$3,_$createComponent(Show24,{get when(){return props.preferences.showSessionTitle()
|
|
6872
7016
|
},get children(){var _el$4=_$createElement("text"),_el$5=_$createElement("b")
|
|
6873
7017
|
_$insertNode(_el$4,_el$5)
|
|
6874
7018
|
_$setProp(_el$4,"wrapMode","word")
|
|
@@ -6876,7 +7020,7 @@ _$insert(_el$5,()=>props.title)
|
|
|
6876
7020
|
_$effect((_$p)=>_$setProp(_el$4,"fg",theme().text,_$p))
|
|
6877
7021
|
return _el$4
|
|
6878
7022
|
}}),null)
|
|
6879
|
-
_$insert(_el$3,_$createComponent(
|
|
7023
|
+
_$insert(_el$3,_$createComponent(Show24,{get when(){return _$memo(()=>!!props.preferences.showSessionDate())()&&created()
|
|
6880
7024
|
},children:(value)=>(()=>{var _el$6=_$createElement("text")
|
|
6881
7025
|
_$insert(_el$6,value)
|
|
6882
7026
|
_$effect((_$p)=>_$setProp(_el$6,"fg",theme().textMuted,_$p))
|
|
@@ -7007,7 +7151,7 @@ return false
|
|
|
7007
7151
|
}
|
|
7008
7152
|
function enabled(value){return typeof value==="function"?value():value!==false
|
|
7009
7153
|
}
|
|
7010
|
-
function createV2Keymap(context){const [revision,setRevision]=
|
|
7154
|
+
function createV2Keymap(context){const [revision,setRevision]=createSignal28(0)
|
|
7011
7155
|
const layers=new Map
|
|
7012
7156
|
let sequence=0
|
|
7013
7157
|
function layerActive(layer){const mode=layer.mode??"base"
|
|
@@ -7191,8 +7335,8 @@ context.ui.router.navigate({type:"plugin",name,data:params})
|
|
|
7191
7335
|
},attention:context.attention,lifecycle:{signal:controller.signal,onDispose}}
|
|
7192
7336
|
api.slots=createV2Slots(context,keymap,(dispose)=>{onDispose(dispose)
|
|
7193
7337
|
})
|
|
7194
|
-
setHostCapabilities(api,{todo:true,lsp:false,titleVisibility:false
|
|
7195
|
-
}
|
|
7338
|
+
setHostCapabilities(api,{todo:true,lsp:false,titleVisibility:false
|
|
7339
|
+
})
|
|
7196
7340
|
return{api,async dispose(){controller.abort()
|
|
7197
7341
|
for(let index=disposers.length-1;index>=0; index--)
|
|
7198
7342
|
await disposers[index]()
|
|
@@ -7264,9 +7408,9 @@ if(item.source.target.startsWith("."))
|
|
|
7264
7408
|
throw new Error("Unrecognized local Navigator source")
|
|
7265
7409
|
await context.client.plugin.update({location:response.location,targets:[item.source.target]})
|
|
7266
7410
|
}}}
|
|
7267
|
-
async function setupNavigator(api,options,readProject){const config=pluginConfig(undefined)
|
|
7411
|
+
async function setupNavigator(api,options,readProject,managedTodo){const config=pluginConfig(undefined)
|
|
7268
7412
|
const configured=await loadConfiguredDefaults(api,options,readProject)
|
|
7269
|
-
const todo=createTodoController(api)
|
|
7413
|
+
const todo=managedTodo??createTodoController(api)
|
|
7270
7414
|
const subagents=createSubagentController(api)
|
|
7271
7415
|
const skills=createSkillController(api)
|
|
7272
7416
|
const preferences=createPreferencesController(api,config,createPreferencesStore(api.state.path.state),configured)
|
|
@@ -7293,7 +7437,7 @@ api.slots.register({order:100,slots:{app(){return _$createComponent(IconProvider
|
|
|
7293
7437
|
},interaction,skills,subagents,mcp
|
|
7294
7438
|
}),_$createComponent(FirstRunWizardPersistence,{api,preferences
|
|
7295
7439
|
}),_$createComponent(StartupSessionBinding,{api,controller:startup
|
|
7296
|
-
}),_$createComponent(UpgradeNotesBinding,{api,preferences,version:"0.
|
|
7440
|
+
}),_$createComponent(UpgradeNotesBinding,{api,preferences,version:"0.18.0"
|
|
7297
7441
|
}),_$createComponent(McpPersistence,{api,controller:mcp
|
|
7298
7442
|
})]
|
|
7299
7443
|
}})
|
|
@@ -7323,33 +7467,34 @@ throw result.error
|
|
|
7323
7467
|
}
|
|
7324
7468
|
return result.data?.type==="text"?result.data.content:undefined
|
|
7325
7469
|
})
|
|
7326
|
-
const versionStatus=createVersionStatus(api,"0.
|
|
7327
|
-
const versionUpdates=createVersionUpdateActions(api,versionStatus,createOpenCodeV1VersionUpdater(api,meta),()=>preferences.rememberNavigatorVersionBeforeUpdate("0.
|
|
7470
|
+
const versionStatus=createVersionStatus(api,"0.18.0")
|
|
7471
|
+
const versionUpdates=createVersionUpdateActions(api,versionStatus,createOpenCodeV1VersionUpdater(api,meta),()=>preferences.rememberNavigatorVersionBeforeUpdate("0.18.0"))
|
|
7328
7472
|
api.slots.register({order:90,slots:{sidebar_footer(_context,props){return _$createComponent(IconProvider,{get style(){return preferences.lspIconStyle
|
|
7329
7473
|
},get multilineCorners(){return preferences.cornerFont
|
|
7330
7474
|
},get children(){return _$createComponent(VersionFooter,{api,get sessionID(){return props.session_id
|
|
7331
|
-
},navigatorVersion:"0.
|
|
7475
|
+
},navigatorVersion:"0.18.0",status:versionStatus,get onOpenCodeUpdate(){return versionUpdates.openCode
|
|
7332
7476
|
},get onNavigatorUpdate(){return versionUpdates.navigator
|
|
7333
7477
|
}})
|
|
7334
7478
|
}})
|
|
7335
7479
|
}}})
|
|
7336
7480
|
}
|
|
7337
7481
|
var setupOpenCodeV2=async (context)=>{const adapter=createOpenCodeV2Api(context)
|
|
7482
|
+
const todo=createNavigatorTodoController(context,adapter.api)
|
|
7338
7483
|
const{mcp,preferences
|
|
7339
7484
|
}=await setupNavigator(adapter.api,context.options,async ()=>{if(!context.client.file?.read)
|
|
7340
7485
|
return
|
|
7341
7486
|
return new TextDecoder().decode(await context.client.file.read({location:context.location,path:".opencode/navigator.json"
|
|
7342
7487
|
}))
|
|
7343
|
-
})
|
|
7344
|
-
const versionStatus=createVersionStatus(adapter.api,"0.
|
|
7345
|
-
const versionUpdates=createVersionUpdateActions(adapter.api,versionStatus,createOpenCodeV2VersionUpdater(context),()=>preferences.rememberNavigatorVersionBeforeUpdate("0.
|
|
7488
|
+
},todo)
|
|
7489
|
+
const versionStatus=createVersionStatus(adapter.api,"0.18.0")
|
|
7490
|
+
const versionUpdates=createVersionUpdateActions(adapter.api,versionStatus,createOpenCodeV2VersionUpdater(context),()=>preferences.rememberNavigatorVersionBeforeUpdate("0.18.0"))
|
|
7346
7491
|
const disposeFooter=context.ui.slot({append:"sidebar.footer",render:()=>_$createComponent(IconProvider,{get style(){return preferences.lspIconStyle
|
|
7347
7492
|
},get multilineCorners(){return preferences.cornerFont
|
|
7348
7493
|
},get children(){var _el$=_$createElement("box")
|
|
7349
7494
|
_$setProp(_el$,"flexDirection","row")
|
|
7350
7495
|
_$setProp(_el$,"justifyContent","space-between")
|
|
7351
7496
|
_$insert(_el$,_$createComponent(VersionSummary,{get api(){return adapter.api
|
|
7352
|
-
},navigatorVersion:"0.
|
|
7497
|
+
},navigatorVersion:"0.18.0",status:versionStatus,get onOpenCodeUpdate(){return versionUpdates.openCode
|
|
7353
7498
|
},get onNavigatorUpdate(){return versionUpdates.navigator
|
|
7354
7499
|
}}),null)
|
|
7355
7500
|
_$insert(_el$,_$createComponent(SettingsFooterButton,{get api(){return adapter.api
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$schema": "https://json.schemastore.org/package.json",
|
|
3
3
|
"name": "opencode-navigator",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.18.0",
|
|
5
5
|
"description": "Search, navigate, and manage OpenCode sessions from the TUI",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"packageManager": "bun@1.4.2",
|
|
@@ -27,6 +27,8 @@
|
|
|
27
27
|
],
|
|
28
28
|
"files": [
|
|
29
29
|
"dist",
|
|
30
|
+
"server.js",
|
|
31
|
+
"rpc.js",
|
|
30
32
|
"assets",
|
|
31
33
|
"scripts/install-font.mjs",
|
|
32
34
|
"scripts/update-local-snapshot.mjs",
|
|
@@ -40,6 +42,12 @@
|
|
|
40
42
|
"exports": {
|
|
41
43
|
"./tui": {
|
|
42
44
|
"import": "./dist/tui.js"
|
|
45
|
+
},
|
|
46
|
+
"./server": {
|
|
47
|
+
"import": "./dist/server.js"
|
|
48
|
+
},
|
|
49
|
+
"./rpc": {
|
|
50
|
+
"import": "./dist/rpc.js"
|
|
43
51
|
}
|
|
44
52
|
},
|
|
45
53
|
"publishConfig": {
|
package/rpc.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { NavigatorTodoRpc } from './dist/rpc.js'
|
package/server.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default } from './dist/server.js'
|