dodo-ai 0.1.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/bin/dodo.js +37 -0
- package/package.json +37 -0
- package/scripts/install-engine.js +137 -0
package/bin/dodo.js
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
const { spawn } = require('child_process');
|
|
4
|
+
const path = require('path');
|
|
5
|
+
const os = require('os');
|
|
6
|
+
const fs = require('fs');
|
|
7
|
+
|
|
8
|
+
function getBinaryPath() {
|
|
9
|
+
const homeDir = os.homedir();
|
|
10
|
+
const ext = os.platform() === 'win32' ? '.exe' : '';
|
|
11
|
+
return path.join(homeDir, '.dodo', 'bin', 'dodo-engine' + ext);
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
const binaryPath = getBinaryPath();
|
|
15
|
+
|
|
16
|
+
if (!fs.existsSync(binaryPath)) {
|
|
17
|
+
console.error('dodo-engine not found. Running installer...');
|
|
18
|
+
require('../scripts/install-engine.js');
|
|
19
|
+
process.exit(0);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
// Pass all arguments to the engine
|
|
23
|
+
const args = process.argv.slice(2);
|
|
24
|
+
|
|
25
|
+
const child = spawn(binaryPath, args, {
|
|
26
|
+
stdio: 'inherit',
|
|
27
|
+
env: process.env
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
child.on('error', (err) => {
|
|
31
|
+
console.error(`Failed to start dodo-engine: ${err.message}`);
|
|
32
|
+
process.exit(1);
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
child.on('close', (code) => {
|
|
36
|
+
process.exit(code || 0);
|
|
37
|
+
});
|
package/package.json
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "dodo-ai",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "An open-source AI coding agent built in Go",
|
|
5
|
+
"author": "Chams Bouzaiene",
|
|
6
|
+
"license": "MIT",
|
|
7
|
+
"repository": {
|
|
8
|
+
"type": "git",
|
|
9
|
+
"url": "git+https://github.com/ChamsBouzaiene/dodo.git"
|
|
10
|
+
},
|
|
11
|
+
"homepage": "https://github.com/ChamsBouzaiene/dodo#readme",
|
|
12
|
+
"bugs": {
|
|
13
|
+
"url": "https://github.com/ChamsBouzaiene/dodo/issues"
|
|
14
|
+
},
|
|
15
|
+
"keywords": [
|
|
16
|
+
"ai",
|
|
17
|
+
"coding-agent",
|
|
18
|
+
"llm",
|
|
19
|
+
"cli",
|
|
20
|
+
"openai",
|
|
21
|
+
"claude",
|
|
22
|
+
"gemini"
|
|
23
|
+
],
|
|
24
|
+
"bin": {
|
|
25
|
+
"dodo": "./bin/dodo.js"
|
|
26
|
+
},
|
|
27
|
+
"scripts": {
|
|
28
|
+
"postinstall": "node ./scripts/install-engine.js"
|
|
29
|
+
},
|
|
30
|
+
"files": [
|
|
31
|
+
"bin/",
|
|
32
|
+
"scripts/"
|
|
33
|
+
],
|
|
34
|
+
"engines": {
|
|
35
|
+
"node": ">=18"
|
|
36
|
+
}
|
|
37
|
+
}
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
const https = require('https');
|
|
4
|
+
const fs = require('fs');
|
|
5
|
+
const path = require('path');
|
|
6
|
+
const { execSync } = require('child_process');
|
|
7
|
+
const os = require('os');
|
|
8
|
+
// Dependencies that might not be installed yet during CI bootstrap
|
|
9
|
+
let tar, AdmZip;
|
|
10
|
+
try {
|
|
11
|
+
tar = require('tar');
|
|
12
|
+
AdmZip = require('adm-zip');
|
|
13
|
+
} catch (e) {
|
|
14
|
+
// Graceful fallback or ignore if just bootstrapping
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
const REPO_OWNER = 'ChamsBouzaiene';
|
|
18
|
+
const REPO_NAME = 'dodo';
|
|
19
|
+
const BINARY_NAME = 'dodo-engine';
|
|
20
|
+
|
|
21
|
+
function getPlatform() {
|
|
22
|
+
const platform = os.platform();
|
|
23
|
+
switch (platform) {
|
|
24
|
+
case 'darwin': return 'darwin';
|
|
25
|
+
case 'linux': return 'linux';
|
|
26
|
+
case 'win32': return 'windows';
|
|
27
|
+
default: throw new Error(`Unsupported platform: ${platform}`);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
function getArch() {
|
|
32
|
+
const arch = os.arch();
|
|
33
|
+
switch (arch) {
|
|
34
|
+
case 'x64': return 'amd64';
|
|
35
|
+
case 'arm64': return 'arm64';
|
|
36
|
+
default: throw new Error(`Unsupported architecture: ${arch}`);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
function getBinaryDir() {
|
|
41
|
+
const homeDir = os.homedir();
|
|
42
|
+
return path.join(homeDir, '.dodo', 'bin');
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
function getBinaryPath() {
|
|
46
|
+
const dir = getBinaryDir();
|
|
47
|
+
const ext = os.platform() === 'win32' ? '.exe' : '';
|
|
48
|
+
return path.join(dir, BINARY_NAME + ext);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
async function getLatestRelease() {
|
|
52
|
+
const pkg = require('../package.json');
|
|
53
|
+
return `v${pkg.version}`;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
function downloadFile(url) {
|
|
57
|
+
return new Promise((resolve, reject) => {
|
|
58
|
+
const makeRequest = (url) => {
|
|
59
|
+
https.get(url, { headers: { 'User-Agent': 'dodo-ai-installer' } }, (response) => {
|
|
60
|
+
if (response.statusCode === 302 || response.statusCode === 301) {
|
|
61
|
+
makeRequest(response.headers.location);
|
|
62
|
+
return;
|
|
63
|
+
}
|
|
64
|
+
if (response.statusCode !== 200) {
|
|
65
|
+
reject(new Error(`Failed to download: ${response.statusCode}`));
|
|
66
|
+
return;
|
|
67
|
+
}
|
|
68
|
+
const chunks = [];
|
|
69
|
+
response.on('data', chunk => chunks.push(chunk));
|
|
70
|
+
response.on('end', () => resolve(Buffer.concat(chunks)));
|
|
71
|
+
response.on('error', reject);
|
|
72
|
+
}).on('error', reject);
|
|
73
|
+
};
|
|
74
|
+
makeRequest(url);
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
async function install() {
|
|
79
|
+
const platform = getPlatform();
|
|
80
|
+
const arch = getArch();
|
|
81
|
+
const version = await getLatestRelease();
|
|
82
|
+
|
|
83
|
+
console.log(`Installing dodo-engine ${version} for ${platform}-${arch}...`);
|
|
84
|
+
|
|
85
|
+
const ext = platform === 'windows' ? 'zip' : 'tar.gz';
|
|
86
|
+
const assetName = `dodo-engine_${platform}_${arch}.${ext}`;
|
|
87
|
+
const downloadUrl = `https://github.com/${REPO_OWNER}/${REPO_NAME}/releases/download/${version}/${assetName}`;
|
|
88
|
+
|
|
89
|
+
const binaryDir = getBinaryDir();
|
|
90
|
+
const binaryPath = getBinaryPath();
|
|
91
|
+
|
|
92
|
+
// Create directory
|
|
93
|
+
fs.mkdirSync(binaryDir, { recursive: true });
|
|
94
|
+
|
|
95
|
+
console.log(`Downloading from ${downloadUrl}...`);
|
|
96
|
+
|
|
97
|
+
try {
|
|
98
|
+
const data = await downloadFile(downloadUrl);
|
|
99
|
+
|
|
100
|
+
if (platform === 'windows') {
|
|
101
|
+
// Handle zip for Windows
|
|
102
|
+
const AdmZip = require('adm-zip');
|
|
103
|
+
const zip = new AdmZip(data);
|
|
104
|
+
zip.extractAllTo(binaryDir, true);
|
|
105
|
+
} else {
|
|
106
|
+
// Handle tar.gz for Unix
|
|
107
|
+
const tempFile = path.join(os.tmpdir(), assetName);
|
|
108
|
+
fs.writeFileSync(tempFile, data);
|
|
109
|
+
execSync(`tar -xzf "${tempFile}" -C "${binaryDir}"`, { stdio: 'inherit' });
|
|
110
|
+
fs.unlinkSync(tempFile);
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
// Make executable on Unix
|
|
114
|
+
if (platform !== 'windows') {
|
|
115
|
+
fs.chmodSync(binaryPath, 0o755);
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
console.log(`Successfully installed dodo-engine to ${binaryPath}`);
|
|
119
|
+
} catch (error) {
|
|
120
|
+
console.error(`Failed to install dodo-engine: ${error.message}`);
|
|
121
|
+
console.error('You may need to install it manually from:');
|
|
122
|
+
console.error(`https://github.com/${REPO_OWNER}/${REPO_NAME}/releases`);
|
|
123
|
+
process.exit(1);
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
// Check if already installed with correct version
|
|
128
|
+
const binaryPath = getBinaryPath();
|
|
129
|
+
if (fs.existsSync(binaryPath)) {
|
|
130
|
+
console.log('dodo-engine already installed.');
|
|
131
|
+
process.exit(0);
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
install().catch(err => {
|
|
135
|
+
console.error(err);
|
|
136
|
+
process.exit(1);
|
|
137
|
+
});
|