opencode-navigator 0.21.8 → 0.22.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/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.21.8",
4
+ "version": "0.22.0",
5
5
  "description": "Search, navigate, and manage OpenCode sessions from the TUI",
6
6
  "type": "module",
7
7
  "packageManager": "bun@1.4.2",
@@ -32,6 +32,7 @@
32
32
  "assets",
33
33
  "scripts/install-font.mjs",
34
34
  "scripts/update-local-snapshot.mjs",
35
+ "scripts/snapshot-runtime.mjs",
35
36
  "scripts/save-project-profile.mjs",
36
37
  "README.md",
37
38
  "PROVIDERS.md",
@@ -104,12 +105,12 @@
104
105
  }
105
106
  },
106
107
  "devDependencies": {
107
- "@opencode-ai/plugin": "1.18.34",
108
- "@opencode-ai/sdk": "1.18.34",
109
- "@opencode/plugin": "2.0.21",
110
- "@opentui/core": "0.5.12",
111
- "@opentui/keymap": "0.5.12",
112
- "@opentui/solid": "0.5.12",
108
+ "@opencode-ai/plugin": "1.19.3",
109
+ "@opencode-ai/sdk": "1.19.3",
110
+ "@opencode/plugin": "2.1.0",
111
+ "@opentui/core": "0.6.6",
112
+ "@opentui/keymap": "0.6.6",
113
+ "@opentui/solid": "0.6.6",
113
114
  "@st1ggy/linter-config": "8.0.0",
114
115
  "@types/bun": "1.4.2",
115
116
  "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
+ }
@@ -5,6 +5,8 @@ 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
+ import { snapshotRuntime } from './snapshot-runtime.mjs'
9
+
8
10
  function command(program, args) {
9
11
  return new Promise((resolveCommand, reject) => {
10
12
  const child = spawn(program, args, { stdio: ['ignore', 'ignore', 'pipe'] })
@@ -33,7 +35,7 @@ export function pinnedSnapshot(wrapper, read = readFile) {
33
35
  })
34
36
  }
35
37
 
36
- async function validate(directory, version) {
38
+ async function validate(directory, version, { checkRuntime = true } = {}) {
37
39
  const metadata = JSON.parse(await readFile(join(directory, 'package.json'), 'utf8'))
38
40
 
39
41
  if (
@@ -48,6 +50,15 @@ async function validate(directory, version) {
48
50
  const changelog = await readFile(join(directory, 'CHANGELOG.md'), 'utf8')
49
51
 
50
52
  if (!changelog.includes(`## [${version}]`)) throw new Error(`Snapshot ${version} has no bundled changelog entry`)
53
+
54
+ // Older installers inherited the predecessor's pins even when a new package
55
+ // declared a runtime manifest. Accept that running source; verify the target.
56
+ if (!checkRuntime) return
57
+
58
+ const runtime = await snapshotRuntime(directory, metadata.dependencies)
59
+
60
+ if (runtime && Object.entries(runtime).some(([name, pinned]) => metadata.dependencies?.[name] !== pinned))
61
+ throw new Error(`Snapshot ${version} has mismatched runtime dependencies`)
51
62
  }
52
63
 
53
64
  export async function updateLocalSnapshot(wrapper, target, operations = {}) {
@@ -59,7 +70,7 @@ export async function updateLocalSnapshot(wrapper, target, operations = {}) {
59
70
 
60
71
  if (target === version) return
61
72
 
62
- await validate(previous, version)
73
+ await validate(previous, version, { checkRuntime: false })
63
74
  const previousMetadata = JSON.parse(await readFile(join(previous, 'package.json'), 'utf8'))
64
75
  const dependencies = previousMetadata.dependencies
65
76
 
@@ -99,7 +110,7 @@ export async function updateLocalSnapshot(wrapper, target, operations = {}) {
99
110
  version: target,
100
111
  private: true,
101
112
  type: 'module',
102
- dependencies,
113
+ dependencies: await snapshotRuntime(staging, dependencies),
103
114
  optionalDependencies: { ...previousMetadata.optionalDependencies, ...metadata.optionalDependencies },
104
115
  }),
105
116
  )