vesper-code 1.0.10 → 1.0.13
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/index.js +158 -3
- package/package.json +6 -6
package/index.js
CHANGED
|
@@ -1,10 +1,15 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
|
-
const { spawn } = require('child_process')
|
|
3
|
+
const { spawn, spawnSync } = require('child_process')
|
|
4
4
|
const fs = require('fs')
|
|
5
|
+
const https = require('https')
|
|
5
6
|
const os = require('os')
|
|
6
7
|
const path = require('path')
|
|
7
8
|
|
|
9
|
+
const PACKAGE_NAME = 'vesper-code'
|
|
10
|
+
const NPM_LATEST_URL = `https://registry.npmjs.org/${PACKAGE_NAME}/latest`
|
|
11
|
+
const UPDATE_CHECK_TIMEOUT_MS = 1500
|
|
12
|
+
|
|
8
13
|
const TARGET_PACKAGES = {
|
|
9
14
|
'darwin-arm64': {
|
|
10
15
|
packageName: 'vesper-code-darwin-arm64',
|
|
@@ -32,6 +37,138 @@ function getTarget() {
|
|
|
32
37
|
return `${process.platform}-${process.arch}`
|
|
33
38
|
}
|
|
34
39
|
|
|
40
|
+
function parseVersion(version) {
|
|
41
|
+
const match = String(version || '').match(/^(\d+)\.(\d+)\.(\d+)/)
|
|
42
|
+
if (!match) return null
|
|
43
|
+
return [Number(match[1]), Number(match[2]), Number(match[3])]
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
function compareVersions(a, b) {
|
|
47
|
+
const parsedA = parseVersion(a)
|
|
48
|
+
const parsedB = parseVersion(b)
|
|
49
|
+
if (!parsedA || !parsedB) return 0
|
|
50
|
+
|
|
51
|
+
for (let index = 0; index < 3; index += 1) {
|
|
52
|
+
const diff = parsedA[index] - parsedB[index]
|
|
53
|
+
if (diff !== 0) return diff
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
return 0
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
function getCurrentVersion() {
|
|
60
|
+
try {
|
|
61
|
+
const packageJsonPath = path.join(__dirname, 'package.json')
|
|
62
|
+
const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf8'))
|
|
63
|
+
return typeof packageJson.version === 'string' ? packageJson.version : null
|
|
64
|
+
} catch {
|
|
65
|
+
return null
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
function fetchLatestVersion() {
|
|
70
|
+
return new Promise((resolve) => {
|
|
71
|
+
const request = https.get(
|
|
72
|
+
NPM_LATEST_URL,
|
|
73
|
+
{
|
|
74
|
+
headers: {
|
|
75
|
+
accept: 'application/json',
|
|
76
|
+
'user-agent': `${PACKAGE_NAME}-cli`,
|
|
77
|
+
},
|
|
78
|
+
},
|
|
79
|
+
(response) => {
|
|
80
|
+
if (response.statusCode !== 200) {
|
|
81
|
+
response.resume()
|
|
82
|
+
resolve(null)
|
|
83
|
+
return
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
let body = ''
|
|
87
|
+
response.setEncoding('utf8')
|
|
88
|
+
response.on('data', (chunk) => {
|
|
89
|
+
body += chunk
|
|
90
|
+
})
|
|
91
|
+
response.on('end', () => {
|
|
92
|
+
try {
|
|
93
|
+
const data = JSON.parse(body)
|
|
94
|
+
resolve(typeof data.version === 'string' ? data.version : null)
|
|
95
|
+
} catch {
|
|
96
|
+
resolve(null)
|
|
97
|
+
}
|
|
98
|
+
})
|
|
99
|
+
},
|
|
100
|
+
)
|
|
101
|
+
|
|
102
|
+
request.on('error', () => resolve(null))
|
|
103
|
+
request.setTimeout(UPDATE_CHECK_TIMEOUT_MS, () => {
|
|
104
|
+
request.destroy()
|
|
105
|
+
resolve(null)
|
|
106
|
+
})
|
|
107
|
+
})
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
function shouldSkipAutoUpdate() {
|
|
111
|
+
return (
|
|
112
|
+
process.env.VESPER_SKIP_AUTO_UPDATE === '1' ||
|
|
113
|
+
process.env.VESPER_NO_AUTO_UPDATE === '1' ||
|
|
114
|
+
process.env.VESPER_AUTO_UPDATE_IN_PROGRESS === '1'
|
|
115
|
+
)
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
function getNpmCommand() {
|
|
119
|
+
return process.platform === 'win32' ? 'npm.cmd' : 'npm'
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
function installLatestVersion(latestVersion) {
|
|
123
|
+
console.error(`Updating Vesper Code to ${latestVersion}...`)
|
|
124
|
+
|
|
125
|
+
const result = spawnSync(
|
|
126
|
+
getNpmCommand(),
|
|
127
|
+
['install', '-g', `${PACKAGE_NAME}@latest`],
|
|
128
|
+
{
|
|
129
|
+
stdio: 'inherit',
|
|
130
|
+
env: {
|
|
131
|
+
...process.env,
|
|
132
|
+
VESPER_AUTO_UPDATE_IN_PROGRESS: '1',
|
|
133
|
+
VESPER_SKIP_AUTO_UPDATE: '1',
|
|
134
|
+
},
|
|
135
|
+
},
|
|
136
|
+
)
|
|
137
|
+
|
|
138
|
+
return result.status === 0
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
async function autoUpdateIfAvailable(options = {}) {
|
|
142
|
+
try {
|
|
143
|
+
const shouldSkip = options.shouldSkipAutoUpdate || shouldSkipAutoUpdate
|
|
144
|
+
if (shouldSkip()) return
|
|
145
|
+
|
|
146
|
+
const readCurrentVersion = options.getCurrentVersion || getCurrentVersion
|
|
147
|
+
const readLatestVersion = options.fetchLatestVersion || fetchLatestVersion
|
|
148
|
+
const installVersion = options.installLatestVersion || installLatestVersion
|
|
149
|
+
|
|
150
|
+
const currentVersion = readCurrentVersion()
|
|
151
|
+
if (!currentVersion) return
|
|
152
|
+
|
|
153
|
+
const latestVersion = await readLatestVersion()
|
|
154
|
+
if (!latestVersion || compareVersions(latestVersion, currentVersion) <= 0) {
|
|
155
|
+
return
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
const installed = installVersion(latestVersion)
|
|
159
|
+
if (installed) {
|
|
160
|
+
console.error(`Vesper Code updated: ${currentVersion} -> ${latestVersion}`)
|
|
161
|
+
return
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
console.error(
|
|
165
|
+
`Vesper Code update failed. Run manually: npm install -g ${PACKAGE_NAME}@latest`,
|
|
166
|
+
)
|
|
167
|
+
} catch {
|
|
168
|
+
// Auto-update must never block or break the CLI.
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
|
|
35
172
|
function getPlatformPackage() {
|
|
36
173
|
const target = getTarget()
|
|
37
174
|
const platformPackage = TARGET_PACKAGES[target]
|
|
@@ -78,7 +215,9 @@ function resolveBinaryPath() {
|
|
|
78
215
|
return binaryPath
|
|
79
216
|
}
|
|
80
217
|
|
|
81
|
-
function main() {
|
|
218
|
+
async function main() {
|
|
219
|
+
await autoUpdateIfAvailable()
|
|
220
|
+
|
|
82
221
|
let binaryPath
|
|
83
222
|
try {
|
|
84
223
|
binaryPath = resolveBinaryPath()
|
|
@@ -114,4 +253,20 @@ function main() {
|
|
|
114
253
|
})
|
|
115
254
|
}
|
|
116
255
|
|
|
117
|
-
main
|
|
256
|
+
if (require.main === module) {
|
|
257
|
+
main().catch((error) => {
|
|
258
|
+
console.error('Failed to start Vesper Code.')
|
|
259
|
+
console.error(error instanceof Error ? error.message : String(error))
|
|
260
|
+
process.exit(1)
|
|
261
|
+
})
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
module.exports = {
|
|
265
|
+
autoUpdateIfAvailable,
|
|
266
|
+
compareVersions,
|
|
267
|
+
fetchLatestVersion,
|
|
268
|
+
getCurrentVersion,
|
|
269
|
+
installLatestVersion,
|
|
270
|
+
parseVersion,
|
|
271
|
+
shouldSkipAutoUpdate,
|
|
272
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "vesper-code",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.13",
|
|
4
4
|
"description": "Vesper Code — AI coding agent",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"bin": {
|
|
@@ -28,11 +28,11 @@
|
|
|
28
28
|
"node": ">=16"
|
|
29
29
|
},
|
|
30
30
|
"optionalDependencies": {
|
|
31
|
-
"vesper-code-darwin-arm64": "1.0.
|
|
32
|
-
"vesper-code-darwin-x64": "1.0.
|
|
33
|
-
"vesper-code-linux-arm64": "1.0.
|
|
34
|
-
"vesper-code-linux-x64": "1.0.
|
|
35
|
-
"vesper-code-windows-x64": "1.0.
|
|
31
|
+
"vesper-code-darwin-arm64": "1.0.13",
|
|
32
|
+
"vesper-code-darwin-x64": "1.0.13",
|
|
33
|
+
"vesper-code-linux-arm64": "1.0.13",
|
|
34
|
+
"vesper-code-linux-x64": "1.0.13",
|
|
35
|
+
"vesper-code-windows-x64": "1.0.13"
|
|
36
36
|
},
|
|
37
37
|
"repository": {
|
|
38
38
|
"type": "git",
|