opencode-navigator 0.22.0 → 0.24.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 +19 -0
- package/HOST_API.md +78 -0
- package/PROVIDERS.md +11 -4
- package/README.md +93 -10
- package/dist/{chunk-dz8cfnfs.js → chunk-bv0nm1tj.js} +4 -4
- package/dist/chunk-fd7394y1.js +17 -0
- package/dist/chunk-pwa1wzer.js +22 -0
- package/dist/layout-preset-actions.js +5 -11
- package/dist/navigator-updates.js +63 -25
- package/dist/provider-limits.js +127 -22
- package/dist/quick-actions-settings.js +2 -8
- package/dist/runtime-dependencies.json +5 -5
- package/dist/runtime-requirements.json +1 -0
- package/dist/server.js +12 -5
- package/dist/sidebar-settings.js +1052 -315
- package/dist/sidebar-shortcuts.js +1 -1
- package/dist/toolbar-settings.js +144 -35
- package/dist/tui.js +765 -564
- package/dist/upgrade-notes.js +87 -0
- package/package.json +20 -18
- package/scripts/snapshot-verifier.mjs +36 -0
- package/scripts/update-local-snapshot.mjs +29 -16
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import {changesSince2,readBundledChangelog2
|
|
2
|
+
} from "./chunk-pwa1wzer.js";
|
|
3
|
+
import {createElement as _$createElement} from "@opentui/solid"
|
|
4
|
+
import {createComponent as _$createComponent} from "@opentui/solid"
|
|
5
|
+
import {onCleanup,onMount} from "solid-js"
|
|
6
|
+
import {createDialogStack} from "./tui.js"
|
|
7
|
+
import {createComponent as _$createComponent2} from "@opentui/solid"
|
|
8
|
+
import {setProp as _$setProp} from "@opentui/solid"
|
|
9
|
+
import {effect as _$effect} from "@opentui/solid"
|
|
10
|
+
import {createTextNode as _$createTextNode} from "@opentui/solid"
|
|
11
|
+
import {insertNode as _$insertNode} from "@opentui/solid"
|
|
12
|
+
import {insert as _$insert} from "@opentui/solid"
|
|
13
|
+
import {createElement as _$createElement2} from "@opentui/solid"
|
|
14
|
+
import {TextAttributes} from "@opentui/core"
|
|
15
|
+
import {useTerminalDimensions} from "@opentui/solid"
|
|
16
|
+
import {For} from "solid-js"
|
|
17
|
+
import {DialogSurface,SelectionBox,useDialogs,useIcons} from "./tui.js"
|
|
18
|
+
function UpgradeNotesDialog(props){const dimensions=useTerminalDimensions()
|
|
19
|
+
const dialogs=useDialogs(props.api)
|
|
20
|
+
const icons=useIcons()
|
|
21
|
+
const theme=()=>props.api.theme.current
|
|
22
|
+
return _$createComponent2(DialogSurface,{get api(){return props.api
|
|
23
|
+
},lift:true,get children(){return [(()=>{var _el$=_$createElement2("text"),_el$2=_$createTextNode(` Navigator updated`)
|
|
24
|
+
_$insertNode(_el$,_el$2)
|
|
25
|
+
_$insert(_el$,()=>icons.icon("update"),_el$2)
|
|
26
|
+
_$effect((_p$)=>{var _v$=theme().text,_v$2=TextAttributes.BOLD
|
|
27
|
+
_v$!==_p$.e&&(_p$.e=_$setProp(_el$,"fg",_v$,_p$.e))
|
|
28
|
+
_v$2!==_p$.t&&(_p$.t=_$setProp(_el$,"attributes",_v$2,_p$.t))
|
|
29
|
+
return _p$
|
|
30
|
+
},{e:undefined,t:undefined
|
|
31
|
+
})
|
|
32
|
+
return _el$
|
|
33
|
+
})(),(()=>{var _el$3=_$createElement2("text"),_el$4=_$createTextNode(`Changes from `),_el$5=_$createTextNode(` to `)
|
|
34
|
+
_$insertNode(_el$3,_el$4)
|
|
35
|
+
_$insertNode(_el$3,_el$5)
|
|
36
|
+
_$insert(_el$3,()=>props.previous,_el$5)
|
|
37
|
+
_$insert(_el$3,()=>props.current,null)
|
|
38
|
+
_$effect((_$p)=>_$setProp(_el$3,"fg",theme().textMuted,_$p))
|
|
39
|
+
return _el$3
|
|
40
|
+
})(),(()=>{var _el$6=_$createElement2("scrollbox"),_el$7=_$createElement2("box")
|
|
41
|
+
_$insertNode(_el$6,_el$7)
|
|
42
|
+
_$setProp(_el$6,"scrollX",false)
|
|
43
|
+
_$setProp(_el$6,"horizontalScrollbarOptions",{visible:false
|
|
44
|
+
})
|
|
45
|
+
_$setProp(_el$6,"verticalScrollbarOptions",{visible:true
|
|
46
|
+
})
|
|
47
|
+
_$setProp(_el$7,"gap",1)
|
|
48
|
+
_$setProp(_el$7,"paddingRight",1)
|
|
49
|
+
_$insert(_el$7,_$createComponent2(For,{get each(){return props.entries
|
|
50
|
+
},children:(entry)=>(()=>{var _el$0=_$createElement2("box"),_el$1=_$createElement2("text"),_el$10=_$createTextNode(`Navigator `)
|
|
51
|
+
_$insertNode(_el$0,_el$1)
|
|
52
|
+
_$setProp(_el$0,"gap",1)
|
|
53
|
+
_$insertNode(_el$1,_el$10)
|
|
54
|
+
_$insert(_el$1,()=>entry.version,null)
|
|
55
|
+
_$insert(_el$0,_$createComponent2(For,{get each(){return entry.changes
|
|
56
|
+
},children:(change)=>(()=>{var _el$11=_$createElement2("text"),_el$12=_$createTextNode(` `)
|
|
57
|
+
_$insertNode(_el$11,_el$12)
|
|
58
|
+
_$setProp(_el$11,"wrapMode","word")
|
|
59
|
+
_$insert(_el$11,()=>icons.icon("selected"),_el$12)
|
|
60
|
+
_$insert(_el$11,change,null)
|
|
61
|
+
_$effect((_$p)=>_$setProp(_el$11,"fg",theme().text,_$p))
|
|
62
|
+
return _el$11
|
|
63
|
+
})()
|
|
64
|
+
}),null)
|
|
65
|
+
_$effect((_p$)=>{var _v$3=theme().accent,_v$4=TextAttributes.BOLD
|
|
66
|
+
_v$3!==_p$.e&&(_p$.e=_$setProp(_el$1,"fg",_v$3,_p$.e))
|
|
67
|
+
_v$4!==_p$.t&&(_p$.t=_$setProp(_el$1,"attributes",_v$4,_p$.t))
|
|
68
|
+
return _p$
|
|
69
|
+
},{e:undefined,t:undefined
|
|
70
|
+
})
|
|
71
|
+
return _el$0
|
|
72
|
+
})()
|
|
73
|
+
}))
|
|
74
|
+
_$effect((_$p)=>_$setProp(_el$6,"height",Math.max(4,Math.min(16,Math.floor(dimensions().height / 2))),_$p))
|
|
75
|
+
return _el$6
|
|
76
|
+
})(),_$createComponent2(SelectionBox,{get backgroundColor(){return theme().primary
|
|
77
|
+
},paddingLeft:1,paddingRight:1,onMouseDown:(event)=>event.stopPropagation(),onMouseUp:(event)=>{event.stopPropagation()
|
|
78
|
+
dialogs.back()
|
|
79
|
+
},get children(){var _el$8=_$createElement2("text")
|
|
80
|
+
_$insertNode(_el$8,_$createTextNode(`Continue`))
|
|
81
|
+
_$effect((_$p)=>_$setProp(_el$8,"fg",theme().selectedListItemText,_$p))
|
|
82
|
+
return _el$8
|
|
83
|
+
}})]
|
|
84
|
+
}})
|
|
85
|
+
}
|
|
86
|
+
export{UpgradeNotesDialog,changesSince2 as changesSince,readBundledChangelog2 as readBundledChangelog
|
|
87
|
+
}
|
package/package.json
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$schema": "https://json.schemastore.org/package.json",
|
|
3
3
|
"name": "opencode-navigator",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.24.0",
|
|
5
5
|
"description": "Search, navigate, and manage OpenCode sessions from the TUI",
|
|
6
6
|
"type": "module",
|
|
7
|
-
"packageManager": "bun@1.4.
|
|
7
|
+
"packageManager": "bun@1.4.4",
|
|
8
8
|
"license": "MIT",
|
|
9
9
|
"author": "St1ggy",
|
|
10
10
|
"repository": {
|
|
@@ -33,9 +33,11 @@
|
|
|
33
33
|
"scripts/install-font.mjs",
|
|
34
34
|
"scripts/update-local-snapshot.mjs",
|
|
35
35
|
"scripts/snapshot-runtime.mjs",
|
|
36
|
+
"scripts/snapshot-verifier.mjs",
|
|
36
37
|
"scripts/save-project-profile.mjs",
|
|
37
38
|
"README.md",
|
|
38
39
|
"PROVIDERS.md",
|
|
40
|
+
"HOST_API.md",
|
|
39
41
|
"CHANGELOG.md",
|
|
40
42
|
"LICENSE"
|
|
41
43
|
],
|
|
@@ -58,7 +60,7 @@
|
|
|
58
60
|
"access": "public"
|
|
59
61
|
},
|
|
60
62
|
"engines": {
|
|
61
|
-
"opencode": "
|
|
63
|
+
"opencode": "1.19.5 || 2.2.5"
|
|
62
64
|
},
|
|
63
65
|
"scripts": {
|
|
64
66
|
"build": "bun run build.ts",
|
|
@@ -81,8 +83,8 @@
|
|
|
81
83
|
"check": "bun run test && bun run typecheck && bun run lint && bun run bundle:size && bun run format:check"
|
|
82
84
|
},
|
|
83
85
|
"peerDependencies": {
|
|
84
|
-
"@opencode-ai/plugin": "
|
|
85
|
-
"@opencode/plugin": "
|
|
86
|
+
"@opencode-ai/plugin": "1.19.5",
|
|
87
|
+
"@opencode/plugin": "2.2.5",
|
|
86
88
|
"@opentui/core": ">=0.4.5",
|
|
87
89
|
"@opentui/solid": ">=0.4.5",
|
|
88
90
|
"solid-js": ">=1.9.12"
|
|
@@ -105,23 +107,23 @@
|
|
|
105
107
|
}
|
|
106
108
|
},
|
|
107
109
|
"devDependencies": {
|
|
108
|
-
"@opencode-ai/plugin": "1.19.
|
|
109
|
-
"@opencode-ai/sdk": "1.19.
|
|
110
|
-
"@opencode/plugin": "2.
|
|
111
|
-
"@opentui/core": "0.
|
|
112
|
-
"@opentui/keymap": "0.
|
|
113
|
-
"@opentui/solid": "0.
|
|
110
|
+
"@opencode-ai/plugin": "1.19.5",
|
|
111
|
+
"@opencode-ai/sdk": "1.19.5",
|
|
112
|
+
"@opencode/plugin": "2.2.5",
|
|
113
|
+
"@opentui/core": "0.8.0",
|
|
114
|
+
"@opentui/keymap": "0.8.0",
|
|
115
|
+
"@opentui/solid": "0.8.0",
|
|
114
116
|
"@st1ggy/linter-config": "8.0.0",
|
|
115
|
-
"@types/bun": "1.4.
|
|
116
|
-
"eslint-plugin-solid": "0.18.
|
|
117
|
-
"oxfmt": "0.
|
|
118
|
-
"oxlint": "1.
|
|
119
|
-
"oxlint-tsgolint": "7.0.
|
|
120
|
-
"solid-js": "1.9.
|
|
117
|
+
"@types/bun": "1.4.4",
|
|
118
|
+
"eslint-plugin-solid": "0.18.1",
|
|
119
|
+
"oxfmt": "0.75.0",
|
|
120
|
+
"oxlint": "1.90.0",
|
|
121
|
+
"oxlint-tsgolint": "7.0.2005",
|
|
122
|
+
"solid-js": "1.9.18",
|
|
121
123
|
"typescript": "6.0.3",
|
|
122
124
|
"web-tree-sitter": "0.25.10"
|
|
123
125
|
},
|
|
124
126
|
"optionalDependencies": {
|
|
125
|
-
"@github/copilot-sdk": "1.0.
|
|
127
|
+
"@github/copilot-sdk": "1.0.28"
|
|
126
128
|
}
|
|
127
129
|
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { readFile } from 'node:fs/promises'
|
|
2
|
+
import { join } from 'node:path'
|
|
3
|
+
|
|
4
|
+
function supports(version, minimum) {
|
|
5
|
+
const value = version.replace(/^v/, '').split('.').map(Number)
|
|
6
|
+
const required = minimum.split('.').map(Number)
|
|
7
|
+
|
|
8
|
+
for (let index = 0; index < 3; index++) {
|
|
9
|
+
if (value[index] !== required[index]) return value[index] > required[index]
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
return true
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export async function snapshotVerifier(directory, probe) {
|
|
16
|
+
const source = await readFile(join(directory, 'dist', 'runtime-requirements.json'), 'utf8').catch((error) => {
|
|
17
|
+
if (error.code !== 'ENOENT') throw error
|
|
18
|
+
})
|
|
19
|
+
|
|
20
|
+
if (!source) return 'node'
|
|
21
|
+
|
|
22
|
+
const requirements = JSON.parse(source)
|
|
23
|
+
|
|
24
|
+
if (requirements.version !== 1 || ['bun', 'node'].some((name) => !/^\d+\.\d+\.\d+$/.test(requirements[name])))
|
|
25
|
+
throw new Error('Navigator package has invalid runtime requirements')
|
|
26
|
+
|
|
27
|
+
for (const runtime of ['bun', 'node']) {
|
|
28
|
+
const version = await probe(runtime).catch(() => '')
|
|
29
|
+
|
|
30
|
+
if (/^v?\d+\.\d+\.\d+$/.test(version.trim()) && supports(version.trim(), requirements[runtime])) return runtime
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
throw new Error(
|
|
34
|
+
`Snapshot verification requires Bun >=${requirements.bun} or Node >=${requirements.node}; the installed snapshot was preserved`,
|
|
35
|
+
)
|
|
36
|
+
}
|
|
@@ -6,17 +6,22 @@ import { basename, dirname, join, resolve } from 'node:path'
|
|
|
6
6
|
import { pathToFileURL } from 'node:url'
|
|
7
7
|
|
|
8
8
|
import { snapshotRuntime } from './snapshot-runtime.mjs'
|
|
9
|
+
import { snapshotVerifier } from './snapshot-verifier.mjs'
|
|
9
10
|
|
|
10
|
-
function command(program, args) {
|
|
11
|
+
function command(program, args, capture = false) {
|
|
11
12
|
return new Promise((resolveCommand, reject) => {
|
|
12
|
-
const child = spawn(program, args, { stdio: ['ignore', 'ignore', 'pipe'] })
|
|
13
|
+
const child = spawn(program, args, { stdio: ['ignore', capture ? 'pipe' : 'ignore', 'pipe'] })
|
|
13
14
|
let error = ''
|
|
15
|
+
let output = ''
|
|
16
|
+
|
|
17
|
+
child.stdout?.setEncoding('utf8')
|
|
18
|
+
child.stdout?.on('data', (chunk) => (output += chunk))
|
|
14
19
|
|
|
15
20
|
child.stderr.setEncoding('utf8')
|
|
16
21
|
child.stderr.on('data', (chunk) => (error += chunk))
|
|
17
22
|
child.on('error', reject)
|
|
18
23
|
child.on('close', (code) => {
|
|
19
|
-
if (code === 0) resolveCommand()
|
|
24
|
+
if (code === 0) resolveCommand(output.trim())
|
|
20
25
|
else reject(new Error(error.trim() || `${program} exited with code ${code}`))
|
|
21
26
|
})
|
|
22
27
|
})
|
|
@@ -61,6 +66,17 @@ async function validate(directory, version, { checkRuntime = true } = {}) {
|
|
|
61
66
|
throw new Error(`Snapshot ${version} has mismatched runtime dependencies`)
|
|
62
67
|
}
|
|
63
68
|
|
|
69
|
+
async function verifySnapshot(directory, runtime) {
|
|
70
|
+
const verifier = runtime ?? (await snapshotVerifier(directory, (program) => command(program, ['--version'], true)))
|
|
71
|
+
const importURL = JSON.stringify(pathToFileURL(join(directory, 'dist', 'tui.js')).href)
|
|
72
|
+
|
|
73
|
+
await command(verifier, [
|
|
74
|
+
'--input-type=module',
|
|
75
|
+
'--eval',
|
|
76
|
+
`const plugin=(await import(${importURL})).default;if(plugin?.id!=='opencode-navigator')throw Error('Invalid Navigator plugin bundle')`,
|
|
77
|
+
])
|
|
78
|
+
}
|
|
79
|
+
|
|
64
80
|
export async function updateLocalSnapshot(wrapper, target, operations = {}) {
|
|
65
81
|
if (!/^\d+\.\d+\.\d+$/.test(target)) throw new Error('Invalid Navigator update version')
|
|
66
82
|
|
|
@@ -81,8 +97,11 @@ export async function updateLocalSnapshot(wrapper, target, operations = {}) {
|
|
|
81
97
|
const replacement = join(root, `.tui-${randomUUID()}.tmp`)
|
|
82
98
|
|
|
83
99
|
try {
|
|
84
|
-
if (existsSync(next))
|
|
85
|
-
|
|
100
|
+
if (existsSync(next)) {
|
|
101
|
+
await validate(next, target)
|
|
102
|
+
|
|
103
|
+
await (operations.verify ? operations.verify(next) : verifySnapshot(next))
|
|
104
|
+
} else {
|
|
86
105
|
await mkdir(staging)
|
|
87
106
|
|
|
88
107
|
if (operations.stage) await operations.stage(staging, target)
|
|
@@ -103,6 +122,10 @@ export async function updateLocalSnapshot(wrapper, target, operations = {}) {
|
|
|
103
122
|
if (metadata.name !== 'opencode-navigator' || metadata.version !== target)
|
|
104
123
|
throw new Error('Downloaded Navigator package does not match the requested version')
|
|
105
124
|
|
|
125
|
+
const verifier = operations.verify
|
|
126
|
+
? undefined
|
|
127
|
+
: await snapshotVerifier(staging, (runtime) => command(runtime, ['--version'], true))
|
|
128
|
+
|
|
106
129
|
await writeFile(
|
|
107
130
|
join(staging, 'package.json'),
|
|
108
131
|
JSON.stringify({
|
|
@@ -129,17 +152,7 @@ export async function updateLocalSnapshot(wrapper, target, operations = {}) {
|
|
|
129
152
|
|
|
130
153
|
await validate(staging, target)
|
|
131
154
|
|
|
132
|
-
|
|
133
|
-
else {
|
|
134
|
-
const bundleURL = pathToFileURL(join(staging, 'dist', 'tui.js')).href
|
|
135
|
-
const importURL = JSON.stringify(bundleURL)
|
|
136
|
-
|
|
137
|
-
await command('node', [
|
|
138
|
-
'--input-type=module',
|
|
139
|
-
'--eval',
|
|
140
|
-
`const plugin=(await import(${importURL})).default;if(plugin?.id!=='opencode-navigator')throw Error('Invalid Navigator plugin bundle')`,
|
|
141
|
-
])
|
|
142
|
-
}
|
|
155
|
+
await (operations.verify ? operations.verify(staging) : verifySnapshot(staging, verifier))
|
|
143
156
|
|
|
144
157
|
await rename(staging, next)
|
|
145
158
|
}
|