opencode-navigator 0.22.0 → 0.23.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 +8 -0
- package/HOST_API.md +59 -0
- package/PROVIDERS.md +11 -4
- package/README.md +30 -10
- package/dist/{chunk-dz8cfnfs.js → chunk-bv0nm1tj.js} +4 -4
- package/dist/layout-preset-actions.js +5 -11
- package/dist/navigator-updates.js +1 -1
- package/dist/provider-limits.js +115 -17
- package/dist/quick-actions-settings.js +2 -8
- package/dist/runtime-dependencies.json +4 -4
- package/dist/runtime-requirements.json +1 -0
- package/dist/server.js +11 -4
- package/dist/sidebar-settings.js +2 -8
- package/dist/sidebar-shortcuts.js +1 -1
- package/dist/toolbar-settings.js +1 -1
- package/dist/tui.js +337 -247
- package/package.json +13 -11
- package/scripts/snapshot-verifier.mjs +36 -0
- package/scripts/update-local-snapshot.mjs +29 -16
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.23.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.0"
|
|
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.0",
|
|
86
88
|
"@opentui/core": ">=0.4.5",
|
|
87
89
|
"@opentui/solid": ">=0.4.5",
|
|
88
90
|
"solid-js": ">=1.9.12"
|
|
@@ -105,12 +107,12 @@
|
|
|
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.0",
|
|
113
|
+
"@opentui/core": "0.7.0",
|
|
114
|
+
"@opentui/keymap": "0.7.0",
|
|
115
|
+
"@opentui/solid": "0.7.0",
|
|
114
116
|
"@st1ggy/linter-config": "8.0.0",
|
|
115
117
|
"@types/bun": "1.4.2",
|
|
116
118
|
"eslint-plugin-solid": "0.18.0",
|
|
@@ -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
|
}
|