codebuff 1.0.511 → 1.0.514
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/README.md +18 -16
- package/index.js +143 -165
- package/package.json +1 -2
package/README.md
CHANGED
|
@@ -1,49 +1,51 @@
|
|
|
1
|
-
# The most powerful coding agent
|
|
1
|
+
# 🚀 Codecane - The most powerful coding agent (STAGING)
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
**⚠️ This is a staging/beta release for testing purposes.**
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
Codecane is a CLI tool that writes code for you.
|
|
6
|
+
|
|
7
|
+
1. Run `codecane` from your project directory
|
|
6
8
|
2. Tell it what to do
|
|
7
9
|
3. It will read and write to files and run commands to produce the code you want
|
|
8
10
|
|
|
9
|
-
Note:
|
|
11
|
+
Note: Codecane will run commands in your terminal as it deems necessary to fulfill your request.
|
|
10
12
|
|
|
11
13
|
## Installation
|
|
12
14
|
|
|
13
|
-
To install
|
|
15
|
+
To install Codecane (staging), run:
|
|
14
16
|
|
|
15
17
|
```bash
|
|
16
|
-
npm install -g
|
|
18
|
+
npm install -g codecane@beta
|
|
17
19
|
```
|
|
18
20
|
|
|
19
21
|
(Use `sudo` if you get a permission error.)
|
|
20
22
|
|
|
21
23
|
## Usage
|
|
22
24
|
|
|
23
|
-
After installation, you can start
|
|
25
|
+
After installation, you can start Codecane by running:
|
|
24
26
|
|
|
25
27
|
```bash
|
|
26
|
-
|
|
28
|
+
codecane [project-directory]
|
|
27
29
|
```
|
|
28
30
|
|
|
29
|
-
If no project directory is specified,
|
|
31
|
+
If no project directory is specified, Codecane will use the current directory.
|
|
30
32
|
|
|
31
|
-
Once running, simply chat with
|
|
33
|
+
Once running, simply chat with Codecane to say what coding task you want done.
|
|
32
34
|
|
|
33
35
|
## Features
|
|
34
36
|
|
|
35
37
|
- Understands your whole codebase
|
|
36
38
|
- Creates and edits multiple files based on your request
|
|
37
39
|
- Can run your tests or type checker or linter; can install packages
|
|
38
|
-
- It's powerful: ask
|
|
40
|
+
- It's powerful: ask Codecane to keep working until it reaches a condition and it will.
|
|
39
41
|
|
|
40
|
-
Our users regularly use
|
|
42
|
+
Our users regularly use Codecane to implement new features, write unit tests, refactor code, write scripts, or give advice.
|
|
41
43
|
|
|
42
44
|
## Knowledge Files
|
|
43
45
|
|
|
44
46
|
To unlock the full benefits of modern LLMs, we recommend storing knowledge alongside your code. Add a `knowledge.md` file anywhere in your project to provide helpful context, guidance, and tips for the LLM as it performs tasks for you.
|
|
45
47
|
|
|
46
|
-
|
|
48
|
+
Codecane can fluently read and write files, so it will add knowledge as it goes. You don't need to write knowledge manually!
|
|
47
49
|
|
|
48
50
|
Some have said every change should be paired with a unit test. In 2024, every change should come with a knowledge update!
|
|
49
51
|
|
|
@@ -52,18 +54,18 @@ Some have said every change should be paired with a unit test. In 2024, every ch
|
|
|
52
54
|
1. Type '/help' or just '/' to see available commands.
|
|
53
55
|
2. Create a `knowledge.md` file and collect specific points of advice. The assistant will use this knowledge to improve its responses.
|
|
54
56
|
3. Type `undo` or `redo` to revert or reapply file changes from the conversation.
|
|
55
|
-
4. Press `Esc` or `Ctrl+C` while
|
|
57
|
+
4. Press `Esc` or `Ctrl+C` while Codecane is generating a response to stop it.
|
|
56
58
|
|
|
57
59
|
## Troubleshooting
|
|
58
60
|
|
|
59
61
|
If you are getting permission errors during installation, try using sudo:
|
|
60
62
|
|
|
61
63
|
```
|
|
62
|
-
sudo npm install -g
|
|
64
|
+
sudo npm install -g codecane@beta
|
|
63
65
|
```
|
|
64
66
|
|
|
65
67
|
If you still have errors, it's a good idea to [reinstall Node](https://nodejs.org/en/download).
|
|
66
68
|
|
|
67
69
|
## Feedback
|
|
68
70
|
|
|
69
|
-
We value your input! Please email your feedback to `founders@codebuff.com`. Thank you for using
|
|
71
|
+
We value your input! Please email your feedback to `founders@codebuff.com`. Thank you for using Codecane!
|
package/index.js
CHANGED
|
@@ -7,52 +7,52 @@ const os = require('os')
|
|
|
7
7
|
const path = require('path')
|
|
8
8
|
const zlib = require('zlib')
|
|
9
9
|
|
|
10
|
-
const { Command } = require('commander')
|
|
11
10
|
const tar = require('tar')
|
|
12
11
|
|
|
13
|
-
const
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
12
|
+
const packageName = 'codebuff'
|
|
13
|
+
|
|
14
|
+
function createConfig(packageName) {
|
|
15
|
+
const homeDir = os.homedir()
|
|
16
|
+
const configDir = path.join(homeDir, '.config', 'manicode')
|
|
17
|
+
const binaryName =
|
|
18
|
+
process.platform === 'win32' ? `${packageName}.exe` : packageName
|
|
19
|
+
|
|
20
|
+
return {
|
|
21
|
+
homeDir,
|
|
22
|
+
configDir,
|
|
23
|
+
binaryName,
|
|
24
|
+
binaryPath: path.join(configDir, binaryName),
|
|
25
|
+
userAgent: `${packageName}-cli`,
|
|
26
|
+
requestTimeout: 20000,
|
|
27
|
+
}
|
|
20
28
|
}
|
|
21
29
|
|
|
22
|
-
CONFIG
|
|
30
|
+
const CONFIG = createConfig(packageName)
|
|
23
31
|
|
|
24
|
-
// Platform target mapping
|
|
25
32
|
const PLATFORM_TARGETS = {
|
|
26
|
-
'linux-x64':
|
|
27
|
-
'linux-arm64':
|
|
28
|
-
'darwin-x64':
|
|
29
|
-
'darwin-arm64':
|
|
30
|
-
'win32-x64':
|
|
33
|
+
'linux-x64': `${packageName}-linux-x64.tar.gz`,
|
|
34
|
+
'linux-arm64': `${packageName}-linux-arm64.tar.gz`,
|
|
35
|
+
'darwin-x64': `${packageName}-darwin-x64.tar.gz`,
|
|
36
|
+
'darwin-arm64': `${packageName}-darwin-arm64.tar.gz`,
|
|
37
|
+
'win32-x64': `${packageName}-win32-x64.tar.gz`,
|
|
31
38
|
}
|
|
32
39
|
|
|
33
|
-
// Terminal utilities
|
|
34
|
-
let isPrintMode = false
|
|
35
40
|
const term = {
|
|
36
41
|
clearLine: () => {
|
|
37
|
-
if (
|
|
42
|
+
if (process.stderr.isTTY) {
|
|
38
43
|
process.stderr.write('\r\x1b[K')
|
|
39
44
|
}
|
|
40
45
|
},
|
|
41
46
|
write: (text) => {
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
process.stderr.write(text)
|
|
45
|
-
}
|
|
47
|
+
term.clearLine()
|
|
48
|
+
process.stderr.write(text)
|
|
46
49
|
},
|
|
47
50
|
writeLine: (text) => {
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
process.stderr.write(text + '\n')
|
|
51
|
-
}
|
|
51
|
+
term.clearLine()
|
|
52
|
+
process.stderr.write(text + '\n')
|
|
52
53
|
},
|
|
53
54
|
}
|
|
54
55
|
|
|
55
|
-
// Utility functions
|
|
56
56
|
function httpGet(url, options = {}) {
|
|
57
57
|
return new Promise((resolve, reject) => {
|
|
58
58
|
const parsedUrl = new URL(url)
|
|
@@ -65,12 +65,6 @@ function httpGet(url, options = {}) {
|
|
|
65
65
|
},
|
|
66
66
|
}
|
|
67
67
|
|
|
68
|
-
// Add GitHub token if available
|
|
69
|
-
const token = process.env.GITHUB_TOKEN
|
|
70
|
-
if (token) {
|
|
71
|
-
reqOptions.headers.Authorization = `Bearer ${token}`
|
|
72
|
-
}
|
|
73
|
-
|
|
74
68
|
const req = https.get(reqOptions, (res) => {
|
|
75
69
|
if (res.statusCode === 302 || res.statusCode === 301) {
|
|
76
70
|
return httpGet(new URL(res.headers.location, url).href, options)
|
|
@@ -93,22 +87,15 @@ function httpGet(url, options = {}) {
|
|
|
93
87
|
async function getLatestVersion() {
|
|
94
88
|
try {
|
|
95
89
|
const res = await httpGet(
|
|
96
|
-
`https://
|
|
90
|
+
`https://registry.npmjs.org/${packageName}/latest`,
|
|
97
91
|
)
|
|
98
92
|
|
|
99
93
|
if (res.statusCode !== 200) return null
|
|
100
94
|
|
|
101
95
|
const body = await streamToString(res)
|
|
96
|
+
const packageData = JSON.parse(body)
|
|
102
97
|
|
|
103
|
-
|
|
104
|
-
const tagMatch = body.match(
|
|
105
|
-
/<id>tag:github\.com,2008:Repository\/\d+\/v(\d+\.\d+\.\d+)<\/id>/,
|
|
106
|
-
)
|
|
107
|
-
if (tagMatch && tagMatch[1]) {
|
|
108
|
-
return tagMatch[1]
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
return null
|
|
98
|
+
return packageData.version || null
|
|
112
99
|
} catch (error) {
|
|
113
100
|
return null
|
|
114
101
|
}
|
|
@@ -124,13 +111,10 @@ function streamToString(stream) {
|
|
|
124
111
|
}
|
|
125
112
|
|
|
126
113
|
function getCurrentVersion() {
|
|
127
|
-
|
|
128
|
-
try {
|
|
129
|
-
if (!fs.existsSync(CONFIG.binaryPath)) {
|
|
130
|
-
resolve('error')
|
|
131
|
-
return
|
|
132
|
-
}
|
|
114
|
+
if (!fs.existsSync(CONFIG.binaryPath)) return null
|
|
133
115
|
|
|
116
|
+
try {
|
|
117
|
+
return new Promise((resolve, reject) => {
|
|
134
118
|
const child = spawn(CONFIG.binaryPath, ['--version'], {
|
|
135
119
|
cwd: os.homedir(),
|
|
136
120
|
stdio: 'pipe',
|
|
@@ -153,9 +137,9 @@ function getCurrentVersion() {
|
|
|
153
137
|
if (!child.killed) {
|
|
154
138
|
child.kill('SIGKILL')
|
|
155
139
|
}
|
|
156
|
-
},
|
|
140
|
+
}, 4000)
|
|
157
141
|
resolve('error')
|
|
158
|
-
},
|
|
142
|
+
}, 4000)
|
|
159
143
|
|
|
160
144
|
child.on('exit', (code) => {
|
|
161
145
|
clearTimeout(timeout)
|
|
@@ -170,31 +154,74 @@ function getCurrentVersion() {
|
|
|
170
154
|
clearTimeout(timeout)
|
|
171
155
|
resolve('error')
|
|
172
156
|
})
|
|
173
|
-
}
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
}
|
|
157
|
+
})
|
|
158
|
+
} catch (error) {
|
|
159
|
+
return 'error'
|
|
160
|
+
}
|
|
177
161
|
}
|
|
178
162
|
|
|
179
163
|
function compareVersions(v1, v2) {
|
|
180
164
|
if (!v1 || !v2) return 0
|
|
181
165
|
|
|
166
|
+
// Always update if the current version is not a valid semver
|
|
167
|
+
// e.g. 1.0.420-beta.1
|
|
182
168
|
if (!v1.match(/^\d+(\.\d+)*$/)) {
|
|
183
169
|
return -1
|
|
184
170
|
}
|
|
185
171
|
|
|
186
|
-
const
|
|
187
|
-
|
|
172
|
+
const parseVersion = (version) => {
|
|
173
|
+
const parts = version.split('-')
|
|
174
|
+
const mainParts = parts[0].split('.').map(Number)
|
|
175
|
+
const prereleaseParts = parts[1] ? parts[1].split('.') : []
|
|
176
|
+
return { main: mainParts, prerelease: prereleaseParts }
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
const p1 = parseVersion(v1)
|
|
180
|
+
const p2 = parseVersion(v2)
|
|
188
181
|
|
|
189
|
-
for (let i = 0; i < Math.max(
|
|
190
|
-
const
|
|
191
|
-
const
|
|
182
|
+
for (let i = 0; i < Math.max(p1.main.length, p2.main.length); i++) {
|
|
183
|
+
const n1 = p1.main[i] || 0
|
|
184
|
+
const n2 = p2.main[i] || 0
|
|
192
185
|
|
|
193
|
-
if (
|
|
194
|
-
if (
|
|
186
|
+
if (n1 < n2) return -1
|
|
187
|
+
if (n1 > n2) return 1
|
|
195
188
|
}
|
|
196
189
|
|
|
197
|
-
|
|
190
|
+
if (p1.prerelease.length === 0 && p2.prerelease.length === 0) {
|
|
191
|
+
return 0
|
|
192
|
+
} else if (p1.prerelease.length === 0) {
|
|
193
|
+
return 1
|
|
194
|
+
} else if (p2.prerelease.length === 0) {
|
|
195
|
+
return -1
|
|
196
|
+
} else {
|
|
197
|
+
for (
|
|
198
|
+
let i = 0;
|
|
199
|
+
i < Math.max(p1.prerelease.length, p2.prerelease.length);
|
|
200
|
+
i++
|
|
201
|
+
) {
|
|
202
|
+
const pr1 = p1.prerelease[i] || ''
|
|
203
|
+
const pr2 = p2.prerelease[i] || ''
|
|
204
|
+
|
|
205
|
+
const isNum1 = !isNaN(parseInt(pr1))
|
|
206
|
+
const isNum2 = !isNaN(parseInt(pr2))
|
|
207
|
+
|
|
208
|
+
if (isNum1 && isNum2) {
|
|
209
|
+
const num1 = parseInt(pr1)
|
|
210
|
+
const num2 = parseInt(pr2)
|
|
211
|
+
if (num1 < num2) return -1
|
|
212
|
+
if (num1 > num2) return 1
|
|
213
|
+
} else if (isNum1 && !isNum2) {
|
|
214
|
+
return 1
|
|
215
|
+
} else if (!isNum1 && isNum2) {
|
|
216
|
+
return -1
|
|
217
|
+
} else if (pr1 < pr2) {
|
|
218
|
+
return -1
|
|
219
|
+
} else if (pr1 > pr2) {
|
|
220
|
+
return 1
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
return 0
|
|
224
|
+
}
|
|
198
225
|
}
|
|
199
226
|
|
|
200
227
|
function formatBytes(bytes) {
|
|
@@ -219,16 +246,30 @@ async function downloadBinary(version) {
|
|
|
219
246
|
throw new Error(`Unsupported platform: ${process.platform} ${process.arch}`)
|
|
220
247
|
}
|
|
221
248
|
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
: `https://codebuff.com/api/releases/download/${version}/${fileName}`
|
|
249
|
+
const downloadUrl = `${
|
|
250
|
+
process.env.NEXT_PUBLIC_CODEBUFF_APP_URL || 'https://codebuff.com'
|
|
251
|
+
}/api/releases/download/${version}/${fileName}`
|
|
226
252
|
|
|
227
|
-
// Ensure config directory exists
|
|
228
253
|
fs.mkdirSync(CONFIG.configDir, { recursive: true })
|
|
229
254
|
|
|
230
255
|
if (fs.existsSync(CONFIG.binaryPath)) {
|
|
231
|
-
|
|
256
|
+
try {
|
|
257
|
+
fs.unlinkSync(CONFIG.binaryPath)
|
|
258
|
+
} catch (err) {
|
|
259
|
+
// Fallback: try renaming the locked/undeletable binary
|
|
260
|
+
const backupPath = CONFIG.binaryPath + `.old.${Date.now()}`
|
|
261
|
+
|
|
262
|
+
try {
|
|
263
|
+
fs.renameSync(CONFIG.binaryPath, backupPath)
|
|
264
|
+
} catch (renameErr) {
|
|
265
|
+
// If we can't unlink OR rename, we can't safely proceed
|
|
266
|
+
throw new Error(
|
|
267
|
+
`Failed to replace existing binary. ` +
|
|
268
|
+
`unlink error: ${err.code || err.message}, ` +
|
|
269
|
+
`rename error: ${renameErr.code || renameErr.message}`,
|
|
270
|
+
)
|
|
271
|
+
}
|
|
272
|
+
}
|
|
232
273
|
}
|
|
233
274
|
|
|
234
275
|
term.write('Downloading...')
|
|
@@ -270,7 +311,6 @@ async function downloadBinary(version) {
|
|
|
270
311
|
})
|
|
271
312
|
|
|
272
313
|
try {
|
|
273
|
-
// Find the extracted binary - it should be named "codebuff" or "codebuff.exe"
|
|
274
314
|
const files = fs.readdirSync(CONFIG.configDir)
|
|
275
315
|
const extractedPath = path.join(CONFIG.configDir, CONFIG.binaryName)
|
|
276
316
|
|
|
@@ -285,20 +325,12 @@ async function downloadBinary(version) {
|
|
|
285
325
|
}
|
|
286
326
|
} catch (error) {
|
|
287
327
|
term.clearLine()
|
|
288
|
-
|
|
289
|
-
console.error(`Extraction failed: ${error.message}`)
|
|
290
|
-
}
|
|
328
|
+
console.error(`Extraction failed: ${error.message}`)
|
|
291
329
|
process.exit(1)
|
|
292
330
|
}
|
|
293
331
|
|
|
294
332
|
term.clearLine()
|
|
295
|
-
|
|
296
|
-
console.log(
|
|
297
|
-
JSON.stringify({ type: 'download', version, status: 'complete' }),
|
|
298
|
-
)
|
|
299
|
-
} else {
|
|
300
|
-
console.log('Download complete! Starting Codebuff...')
|
|
301
|
-
}
|
|
333
|
+
console.log('Download complete! Starting Codebuff...')
|
|
302
334
|
}
|
|
303
335
|
|
|
304
336
|
async function ensureBinaryExists() {
|
|
@@ -309,17 +341,8 @@ async function ensureBinaryExists() {
|
|
|
309
341
|
|
|
310
342
|
const version = await getLatestVersion()
|
|
311
343
|
if (!version) {
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
JSON.stringify({
|
|
315
|
-
type: 'error',
|
|
316
|
-
message: 'Failed to determine latest version.',
|
|
317
|
-
}),
|
|
318
|
-
)
|
|
319
|
-
} else {
|
|
320
|
-
console.error('❌ Failed to determine latest version')
|
|
321
|
-
console.error('Please check your internet connection and try again')
|
|
322
|
-
}
|
|
344
|
+
console.error('❌ Failed to determine latest version')
|
|
345
|
+
console.error('Please check your internet connection and try again')
|
|
323
346
|
process.exit(1)
|
|
324
347
|
}
|
|
325
348
|
|
|
@@ -327,45 +350,31 @@ async function ensureBinaryExists() {
|
|
|
327
350
|
await downloadBinary(version)
|
|
328
351
|
} catch (error) {
|
|
329
352
|
term.clearLine()
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
JSON.stringify({
|
|
333
|
-
type: 'error',
|
|
334
|
-
message: `Failed to download codebuff: ${error.message}`,
|
|
335
|
-
}),
|
|
336
|
-
)
|
|
337
|
-
} else {
|
|
338
|
-
console.error('❌ Failed to download codebuff:', error.message)
|
|
339
|
-
console.error('Please check your internet connection and try again')
|
|
340
|
-
}
|
|
353
|
+
console.error('❌ Failed to download codebuff:', error.message)
|
|
354
|
+
console.error('Please check your internet connection and try again')
|
|
341
355
|
process.exit(1)
|
|
342
356
|
}
|
|
343
357
|
}
|
|
344
358
|
|
|
345
|
-
async function checkForUpdates(runningProcess, exitListener
|
|
359
|
+
async function checkForUpdates(runningProcess, exitListener) {
|
|
346
360
|
try {
|
|
347
361
|
const currentVersion = await getCurrentVersion()
|
|
362
|
+
if (!currentVersion) return
|
|
348
363
|
|
|
349
364
|
const latestVersion = await getLatestVersion()
|
|
350
365
|
if (!latestVersion) return
|
|
351
366
|
|
|
352
367
|
if (
|
|
353
|
-
// Download new version if current binary errors.
|
|
354
368
|
currentVersion === 'error' ||
|
|
355
369
|
compareVersions(currentVersion, latestVersion) < 0
|
|
356
370
|
) {
|
|
357
371
|
term.clearLine()
|
|
358
372
|
|
|
359
|
-
// Remove the specific exit listener to prevent it from interfering with the update
|
|
360
373
|
runningProcess.removeListener('exit', exitListener)
|
|
361
|
-
|
|
362
|
-
// Kill the running process
|
|
363
374
|
runningProcess.kill('SIGTERM')
|
|
364
375
|
|
|
365
|
-
// Wait for the process to actually exit
|
|
366
376
|
await new Promise((resolve) => {
|
|
367
377
|
runningProcess.on('exit', resolve)
|
|
368
|
-
// Fallback timeout in case the process doesn't exit gracefully
|
|
369
378
|
setTimeout(() => {
|
|
370
379
|
if (!runningProcess.killed) {
|
|
371
380
|
runningProcess.kill('SIGKILL')
|
|
@@ -374,76 +383,45 @@ async function checkForUpdates(runningProcess, exitListener, retry) {
|
|
|
374
383
|
}, 5000)
|
|
375
384
|
})
|
|
376
385
|
|
|
377
|
-
|
|
378
|
-
console.log(`Update available: ${currentVersion} → ${latestVersion}`)
|
|
379
|
-
}
|
|
386
|
+
console.log(`Update available: ${currentVersion} → ${latestVersion}`)
|
|
380
387
|
|
|
381
388
|
await downloadBinary(latestVersion)
|
|
382
389
|
|
|
383
|
-
|
|
390
|
+
const newChild = spawn(CONFIG.binaryPath, process.argv.slice(2), {
|
|
391
|
+
stdio: 'inherit',
|
|
392
|
+
detached: false,
|
|
393
|
+
})
|
|
394
|
+
|
|
395
|
+
newChild.on('exit', (code) => {
|
|
396
|
+
process.exit(code || 0)
|
|
397
|
+
})
|
|
398
|
+
|
|
399
|
+
return new Promise(() => {})
|
|
384
400
|
}
|
|
385
401
|
} catch (error) {
|
|
386
|
-
//
|
|
402
|
+
// Ignore update failures
|
|
387
403
|
}
|
|
388
404
|
}
|
|
389
405
|
|
|
390
|
-
async function main(
|
|
391
|
-
isPrintMode = printMode
|
|
406
|
+
async function main() {
|
|
392
407
|
await ensureBinaryExists()
|
|
393
408
|
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
const child = spawn(CONFIG.binaryPath, process.argv.slice(2), {
|
|
398
|
-
stdio: 'inherit',
|
|
399
|
-
})
|
|
409
|
+
const child = spawn(CONFIG.binaryPath, process.argv.slice(2), {
|
|
410
|
+
stdio: 'inherit',
|
|
411
|
+
})
|
|
400
412
|
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
}
|
|
413
|
+
const exitListener = (code) => {
|
|
414
|
+
process.exit(code || 0)
|
|
415
|
+
}
|
|
405
416
|
|
|
406
|
-
|
|
417
|
+
child.on('exit', exitListener)
|
|
407
418
|
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
if (!error) {
|
|
412
|
-
checkForUpdates(child, exitListener, () => main(false, isPrintMode))
|
|
413
|
-
}
|
|
414
|
-
}, 100)
|
|
415
|
-
}
|
|
416
|
-
} catch (err) {
|
|
417
|
-
error = err
|
|
418
|
-
if (firstRun) {
|
|
419
|
-
if (!isPrintMode) {
|
|
420
|
-
console.error('❌ Codebuff failed to start:', error.message)
|
|
421
|
-
console.log('Redownloading Codebuff...')
|
|
422
|
-
}
|
|
423
|
-
// Binary could be corrupted (killed before download completed), so delete and retry.
|
|
424
|
-
fs.unlinkSync(CONFIG.binaryPath)
|
|
425
|
-
await main(false, isPrintMode)
|
|
426
|
-
}
|
|
427
|
-
}
|
|
419
|
+
setTimeout(() => {
|
|
420
|
+
checkForUpdates(child, exitListener)
|
|
421
|
+
}, 100)
|
|
428
422
|
}
|
|
429
423
|
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
program
|
|
433
|
-
.name('codebuff')
|
|
434
|
-
.description('AI coding agent')
|
|
435
|
-
.helpOption(false)
|
|
436
|
-
.option('-p, --print', 'print mode - suppress wrapper output')
|
|
437
|
-
.allowUnknownOption()
|
|
438
|
-
.parse()
|
|
439
|
-
|
|
440
|
-
const options = program.opts()
|
|
441
|
-
isPrintMode = options.print
|
|
442
|
-
|
|
443
|
-
// Run the main function
|
|
444
|
-
main(true, isPrintMode).catch((error) => {
|
|
445
|
-
if (!isPrintMode) {
|
|
446
|
-
console.error('❌ Unexpected error:', error.message)
|
|
447
|
-
}
|
|
424
|
+
main().catch((error) => {
|
|
425
|
+
console.error('❌ Unexpected error:', error.message)
|
|
448
426
|
process.exit(1)
|
|
449
427
|
})
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "codebuff",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.514",
|
|
4
4
|
"description": "AI coding agent",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"bin": {
|
|
@@ -27,7 +27,6 @@
|
|
|
27
27
|
"node": ">=16"
|
|
28
28
|
},
|
|
29
29
|
"dependencies": {
|
|
30
|
-
"commander": "^12.0.0",
|
|
31
30
|
"tar": "^6.2.0"
|
|
32
31
|
},
|
|
33
32
|
"repository": {
|