opencode-navigator 0.21.8 → 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 +17 -1
- package/HOST_API.md +59 -0
- package/PROVIDERS.md +11 -4
- package/README.md +118 -24
- package/dist/chunk-bv0nm1tj.js +9 -0
- package/dist/chunk-qmntexwm.js +0 -0
- package/dist/chunk-v6bz59xn.js +20 -0
- package/dist/icon-picker.js +175 -0
- package/dist/layout-preset-actions.js +8 -30
- package/dist/navigator-updates.js +12 -4
- package/dist/project-profile.js +12 -4
- package/dist/provider-limits.js +117 -17
- package/dist/quick-actions-settings.js +6 -20
- package/dist/rpc.js +1 -0
- package/dist/runtime-dependencies.json +10 -0
- package/dist/runtime-requirements.json +1 -0
- package/dist/server.js +27 -58
- package/dist/settings-import.js +4 -3
- package/dist/sidebar-settings.js +822 -0
- package/dist/sidebar-shortcuts.js +261 -0
- package/dist/toolbar-settings.js +161 -0
- package/dist/tui.js +1337 -1288
- package/package.json +14 -11
- package/scripts/snapshot-runtime.mjs +32 -0
- package/scripts/snapshot-verifier.mjs +36 -0
- package/scripts/update-local-snapshot.mjs +43 -19
- package/dist/chunk-d1bws32s.js +0 -8
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": {
|
|
@@ -32,9 +32,12 @@
|
|
|
32
32
|
"assets",
|
|
33
33
|
"scripts/install-font.mjs",
|
|
34
34
|
"scripts/update-local-snapshot.mjs",
|
|
35
|
+
"scripts/snapshot-runtime.mjs",
|
|
36
|
+
"scripts/snapshot-verifier.mjs",
|
|
35
37
|
"scripts/save-project-profile.mjs",
|
|
36
38
|
"README.md",
|
|
37
39
|
"PROVIDERS.md",
|
|
40
|
+
"HOST_API.md",
|
|
38
41
|
"CHANGELOG.md",
|
|
39
42
|
"LICENSE"
|
|
40
43
|
],
|
|
@@ -57,7 +60,7 @@
|
|
|
57
60
|
"access": "public"
|
|
58
61
|
},
|
|
59
62
|
"engines": {
|
|
60
|
-
"opencode": "
|
|
63
|
+
"opencode": "1.19.5 || 2.2.0"
|
|
61
64
|
},
|
|
62
65
|
"scripts": {
|
|
63
66
|
"build": "bun run build.ts",
|
|
@@ -80,8 +83,8 @@
|
|
|
80
83
|
"check": "bun run test && bun run typecheck && bun run lint && bun run bundle:size && bun run format:check"
|
|
81
84
|
},
|
|
82
85
|
"peerDependencies": {
|
|
83
|
-
"@opencode-ai/plugin": "
|
|
84
|
-
"@opencode/plugin": "
|
|
86
|
+
"@opencode-ai/plugin": "1.19.5",
|
|
87
|
+
"@opencode/plugin": "2.2.0",
|
|
85
88
|
"@opentui/core": ">=0.4.5",
|
|
86
89
|
"@opentui/solid": ">=0.4.5",
|
|
87
90
|
"solid-js": ">=1.9.12"
|
|
@@ -104,12 +107,12 @@
|
|
|
104
107
|
}
|
|
105
108
|
},
|
|
106
109
|
"devDependencies": {
|
|
107
|
-
"@opencode-ai/plugin": "1.
|
|
108
|
-
"@opencode-ai/sdk": "1.
|
|
109
|
-
"@opencode/plugin": "2.0
|
|
110
|
-
"@opentui/core": "0.
|
|
111
|
-
"@opentui/keymap": "0.
|
|
112
|
-
"@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",
|
|
113
116
|
"@st1ggy/linter-config": "8.0.0",
|
|
114
117
|
"@types/bun": "1.4.2",
|
|
115
118
|
"eslint-plugin-solid": "0.18.0",
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { readFile } from 'node:fs/promises'
|
|
2
|
+
import { join } from 'node:path'
|
|
3
|
+
|
|
4
|
+
const PACKAGES = ['@opencode/plugin', '@opentui/core', '@opentui/keymap', '@opentui/solid', 'solid-js']
|
|
5
|
+
|
|
6
|
+
export async function snapshotRuntime(directory, fallback) {
|
|
7
|
+
let source
|
|
8
|
+
|
|
9
|
+
try {
|
|
10
|
+
source = await readFile(join(directory, 'dist', 'runtime-dependencies.json'), 'utf8')
|
|
11
|
+
} catch (error) {
|
|
12
|
+
if (error.code === 'ENOENT') return fallback
|
|
13
|
+
|
|
14
|
+
throw error
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
const manifest = JSON.parse(source)
|
|
18
|
+
const dependencies = manifest?.dependencies
|
|
19
|
+
|
|
20
|
+
if (
|
|
21
|
+
manifest?.version !== 1 ||
|
|
22
|
+
Object.keys(manifest).some((key) => !['version', 'dependencies'].includes(key)) ||
|
|
23
|
+
!dependencies ||
|
|
24
|
+
typeof dependencies !== 'object' ||
|
|
25
|
+
Array.isArray(dependencies) ||
|
|
26
|
+
Object.keys(dependencies).length !== PACKAGES.length ||
|
|
27
|
+
PACKAGES.some((name) => typeof dependencies[name] !== 'string' || !/^\d+\.\d+\.\d+$/.test(dependencies[name]))
|
|
28
|
+
)
|
|
29
|
+
throw new Error('Navigator package has an invalid runtime dependency manifest')
|
|
30
|
+
|
|
31
|
+
return Object.fromEntries(PACKAGES.map((name) => [name, dependencies[name]]))
|
|
32
|
+
}
|
|
@@ -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
|
+
}
|
|
@@ -5,16 +5,23 @@ import { mkdir, readFile, rename, rm, writeFile } from 'node:fs/promises'
|
|
|
5
5
|
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'
|
|
10
|
+
|
|
11
|
+
function command(program, args, capture = false) {
|
|
9
12
|
return new Promise((resolveCommand, reject) => {
|
|
10
|
-
const child = spawn(program, args, { stdio: ['ignore', 'ignore', 'pipe'] })
|
|
13
|
+
const child = spawn(program, args, { stdio: ['ignore', capture ? 'pipe' : 'ignore', 'pipe'] })
|
|
11
14
|
let error = ''
|
|
15
|
+
let output = ''
|
|
16
|
+
|
|
17
|
+
child.stdout?.setEncoding('utf8')
|
|
18
|
+
child.stdout?.on('data', (chunk) => (output += chunk))
|
|
12
19
|
|
|
13
20
|
child.stderr.setEncoding('utf8')
|
|
14
21
|
child.stderr.on('data', (chunk) => (error += chunk))
|
|
15
22
|
child.on('error', reject)
|
|
16
23
|
child.on('close', (code) => {
|
|
17
|
-
if (code === 0) resolveCommand()
|
|
24
|
+
if (code === 0) resolveCommand(output.trim())
|
|
18
25
|
else reject(new Error(error.trim() || `${program} exited with code ${code}`))
|
|
19
26
|
})
|
|
20
27
|
})
|
|
@@ -33,7 +40,7 @@ export function pinnedSnapshot(wrapper, read = readFile) {
|
|
|
33
40
|
})
|
|
34
41
|
}
|
|
35
42
|
|
|
36
|
-
async function validate(directory, version) {
|
|
43
|
+
async function validate(directory, version, { checkRuntime = true } = {}) {
|
|
37
44
|
const metadata = JSON.parse(await readFile(join(directory, 'package.json'), 'utf8'))
|
|
38
45
|
|
|
39
46
|
if (
|
|
@@ -48,6 +55,26 @@ async function validate(directory, version) {
|
|
|
48
55
|
const changelog = await readFile(join(directory, 'CHANGELOG.md'), 'utf8')
|
|
49
56
|
|
|
50
57
|
if (!changelog.includes(`## [${version}]`)) throw new Error(`Snapshot ${version} has no bundled changelog entry`)
|
|
58
|
+
|
|
59
|
+
// Older installers inherited the predecessor's pins even when a new package
|
|
60
|
+
// declared a runtime manifest. Accept that running source; verify the target.
|
|
61
|
+
if (!checkRuntime) return
|
|
62
|
+
|
|
63
|
+
const runtime = await snapshotRuntime(directory, metadata.dependencies)
|
|
64
|
+
|
|
65
|
+
if (runtime && Object.entries(runtime).some(([name, pinned]) => metadata.dependencies?.[name] !== pinned))
|
|
66
|
+
throw new Error(`Snapshot ${version} has mismatched runtime dependencies`)
|
|
67
|
+
}
|
|
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
|
+
])
|
|
51
78
|
}
|
|
52
79
|
|
|
53
80
|
export async function updateLocalSnapshot(wrapper, target, operations = {}) {
|
|
@@ -59,7 +86,7 @@ export async function updateLocalSnapshot(wrapper, target, operations = {}) {
|
|
|
59
86
|
|
|
60
87
|
if (target === version) return
|
|
61
88
|
|
|
62
|
-
await validate(previous, version)
|
|
89
|
+
await validate(previous, version, { checkRuntime: false })
|
|
63
90
|
const previousMetadata = JSON.parse(await readFile(join(previous, 'package.json'), 'utf8'))
|
|
64
91
|
const dependencies = previousMetadata.dependencies
|
|
65
92
|
|
|
@@ -70,8 +97,11 @@ export async function updateLocalSnapshot(wrapper, target, operations = {}) {
|
|
|
70
97
|
const replacement = join(root, `.tui-${randomUUID()}.tmp`)
|
|
71
98
|
|
|
72
99
|
try {
|
|
73
|
-
if (existsSync(next))
|
|
74
|
-
|
|
100
|
+
if (existsSync(next)) {
|
|
101
|
+
await validate(next, target)
|
|
102
|
+
|
|
103
|
+
await (operations.verify ? operations.verify(next) : verifySnapshot(next))
|
|
104
|
+
} else {
|
|
75
105
|
await mkdir(staging)
|
|
76
106
|
|
|
77
107
|
if (operations.stage) await operations.stage(staging, target)
|
|
@@ -92,6 +122,10 @@ export async function updateLocalSnapshot(wrapper, target, operations = {}) {
|
|
|
92
122
|
if (metadata.name !== 'opencode-navigator' || metadata.version !== target)
|
|
93
123
|
throw new Error('Downloaded Navigator package does not match the requested version')
|
|
94
124
|
|
|
125
|
+
const verifier = operations.verify
|
|
126
|
+
? undefined
|
|
127
|
+
: await snapshotVerifier(staging, (runtime) => command(runtime, ['--version'], true))
|
|
128
|
+
|
|
95
129
|
await writeFile(
|
|
96
130
|
join(staging, 'package.json'),
|
|
97
131
|
JSON.stringify({
|
|
@@ -99,7 +133,7 @@ export async function updateLocalSnapshot(wrapper, target, operations = {}) {
|
|
|
99
133
|
version: target,
|
|
100
134
|
private: true,
|
|
101
135
|
type: 'module',
|
|
102
|
-
dependencies,
|
|
136
|
+
dependencies: await snapshotRuntime(staging, dependencies),
|
|
103
137
|
optionalDependencies: { ...previousMetadata.optionalDependencies, ...metadata.optionalDependencies },
|
|
104
138
|
}),
|
|
105
139
|
)
|
|
@@ -118,17 +152,7 @@ export async function updateLocalSnapshot(wrapper, target, operations = {}) {
|
|
|
118
152
|
|
|
119
153
|
await validate(staging, target)
|
|
120
154
|
|
|
121
|
-
|
|
122
|
-
else {
|
|
123
|
-
const bundleURL = pathToFileURL(join(staging, 'dist', 'tui.js')).href
|
|
124
|
-
const importURL = JSON.stringify(bundleURL)
|
|
125
|
-
|
|
126
|
-
await command('node', [
|
|
127
|
-
'--input-type=module',
|
|
128
|
-
'--eval',
|
|
129
|
-
`const plugin=(await import(${importURL})).default;if(plugin?.id!=='opencode-navigator')throw Error('Invalid Navigator plugin bundle')`,
|
|
130
|
-
])
|
|
131
|
-
}
|
|
155
|
+
await (operations.verify ? operations.verify(staging) : verifySnapshot(staging, verifier))
|
|
132
156
|
|
|
133
157
|
await rename(staging, next)
|
|
134
158
|
}
|
package/dist/chunk-d1bws32s.js
DELETED
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
var PLUGIN_ID="opencode-navigator"
|
|
2
|
-
var TOGGLE_COMMAND=`${PLUGIN_ID}.toggle`
|
|
3
|
-
var FOCUS_COMMAND=`${PLUGIN_ID}.focus`
|
|
4
|
-
var SEARCH_COMMAND=`${PLUGIN_ID}.search`;
|
|
5
|
-
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"]
|
|
6
|
-
var SECTION_DEFINITIONS=[{name:"limits",label:"Limits"},{name:"todo",label:"Todo"},{name:"subagents",label:"Subagents"},{name:"skills",label:"Skills"},{name:"quick_actions",label:"Quick actions"},{name:"lsp",label:"LSP"},{name:"mcp",label:"MCP"}];
|
|
7
|
-
var MAX_LIMITS_REFRESH_MINUTES=Math.floor(2147483647 / 60000)
|
|
8
|
-
export{QUICK_ACTION_IDS,SECTION_DEFINITIONS,PLUGIN_ID}
|