Skip to content

Commit 9a8e493

Browse files
committed
feat: add building to single executable
- add build script with compilation to binary - update tsconfig for correct compilation - bump bun version to 1.1.30 to make it work with compilation and running compiled version - add sourcemaps to compiled file to make errors & stacktraces point to their original locations instead of the transpiled location - add gh release action for building binary on push of version tag - fix some type errors - update readme to reflect build and distribution process - add required bun version to package.json and readme. - describe packages installation thoublesheeting for dynamic imports and bun --compile
1 parent 5ec826f commit 9a8e493

File tree

9 files changed

+289
-33
lines changed

9 files changed

+289
-33
lines changed

.github/workflows/release.yml

+45
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
name: Build and Release
2+
3+
on:
4+
push:
5+
tags:
6+
- "v*.*.*"
7+
8+
jobs:
9+
build:
10+
runs-on: ubuntu-latest
11+
steps:
12+
- name: Checkout code
13+
uses: actions/checkout@v3
14+
15+
- name: Setup Bun
16+
uses: oven-sh/setup-bun@v1
17+
with:
18+
bun-version: latest
19+
20+
- name: Install dependencies
21+
run: bun install
22+
23+
- name: Build project
24+
run: bun run build
25+
26+
- name: Create Release
27+
id: create_release
28+
uses: actions/create-release@v1
29+
env:
30+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
31+
with:
32+
tag_name: ${{ github.ref }}
33+
release_name: Release ${{ github.ref }}
34+
draft: false
35+
prerelease: false
36+
37+
- name: Upload Release Asset
38+
uses: actions/upload-release-asset@v1
39+
env:
40+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
41+
with:
42+
upload_url: ${{ steps.create_release.outputs.upload_url }}
43+
asset_path: ./dist/ai-console-agent
44+
asset_name: ai-console-agent
45+
asset_content_type: application/octet-stream

README.md

+142-2
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ AI Console Agent is an advanced command-line tool that uses artificial intellige
88
- [Prerequisites](#prerequisites)
99
- [Installation](#installation)
1010
- [Usage](#usage)
11+
- [Compilation and Distribution](#compilation-and-distribution)
1112
- [Safety and Limitations](#safety-and-limitations)
1213
- [Development Status](#development-status)
1314
- [Contributing](#contributing)
@@ -71,6 +72,146 @@ bun run src/index.ts "Show me the disk usage of the current directory"
7172

7273
The agent will interpret your request, execute the necessary commands, and provide you with the results.
7374

75+
## Compilation and Distribution
76+
77+
### Prerequisites
78+
79+
This project requires Bun version 1.1.30 or later. To install Bun, follow the instructions at https://bun.sh/.
80+
81+
82+
### Compilation Process
83+
84+
To compile the AI Console Agent into a standalone executable with source maps, follow these steps:
85+
86+
1. Ensure all project dependencies are installed:
87+
88+
```
89+
bun install
90+
```
91+
92+
2. Run the build script:
93+
94+
```
95+
bun run build
96+
```
97+
98+
3. Upon successful compilation, you'll see a message similar to:
99+
100+
```
101+
Build completed successfully. Executable: /path/to/ai-console-agent/dist/ai-console-agent
102+
```
103+
104+
4. The compiled executable will be created in the `dist` directory as `ai-console-agent`, along with source map files.
105+
106+
### Running the Compiled Executable
107+
108+
After successful compilation, run the AI Console Agent using:
109+
110+
```
111+
./dist/ai-console-agent "Your command here"
112+
```
113+
114+
This executable includes all necessary dependencies and can be distributed as a standalone program.
115+
116+
### Release Process for Developers
117+
118+
To create a new release:
119+
120+
1. Ensure all changes are committed and pushed to the main branch.
121+
122+
2. Update the version number in `package.json`.
123+
124+
3. Create a new tag with the version number:
125+
126+
```
127+
git tag v1.0.0 # Replace with your version number
128+
```
129+
130+
4. Push the tag to GitHub:
131+
132+
```
133+
git push origin v1.0.0 # Replace with your version number
134+
```
135+
136+
5. The GitHub Actions workflow will automatically:
137+
138+
- Build the project
139+
- Create a new release
140+
- Attach the compiled executable to the release
141+
142+
6. Once complete, you can find the new release on the GitHub repository's releases page.
143+
144+
### Troubleshooting Compilation
145+
146+
Compilation is done using Bun bundler that allows compiling TypeScript code into one executable file.
147+
Read about it here: https://bun.sh/docs/bundler/executables
148+
149+
If you encounter errors related to missing packages during compilation, follow these steps:
150+
151+
1. Identify the missing packages from the error messages. Common missing packages might include:
152+
153+
- pg
154+
- @xenova/transformers
155+
- pgvector
156+
157+
2. Install these packages as dev dependencies:
158+
159+
```
160+
bun add -d packageName1 packageName2 ...
161+
```
162+
163+
For example:
164+
165+
```
166+
bun add -d pg @xenova/transformers pgvector
167+
```
168+
169+
3. Update your `package.json` to include these as dev dependencies:
170+
171+
```json
172+
{
173+
"devDependencies": {
174+
"@types/bun": "latest",
175+
"@xenova/transformers": "^2.17.2",
176+
"pg": "^8.13.0",
177+
"pgvector": "^0.2.0"
178+
},
179+
"dependencies": {
180+
"chalk": "^5.3.0",
181+
"dotenv": "^16.0.0",
182+
"llamaindex": "^0.6.18"
183+
}
184+
}
185+
```
186+
187+
4. Run the build process again:
188+
```
189+
bun run build
190+
```
191+
192+
Note: This issue may occur if there are changes in the `llamaindex` package or its dependencies. Always check for updates and be prepared to add new dev dependencies as needed.
193+
194+
### Development Run
195+
196+
For development and testing purposes, you can run the project directly without compilation:
197+
198+
```
199+
bun run src/index.ts "Your natural language command or question here"
200+
```
201+
202+
This method works fine for development without requiring the additional setup needed for compilation.
203+
204+
### Keeping Dependencies Updated
205+
206+
To ensure the project remains up-to-date:
207+
208+
1. Periodically update the project dependencies:
209+
```
210+
bun update
211+
```
212+
2. After updating, perform a fresh compilation process to ensure compatibility with the latest versions.
213+
3. Test the newly compiled executable thoroughly before distribution.
214+
74215
## Safety and Limitations
75216

76217
- The agent creates backups before modifying important files.
@@ -86,7 +227,6 @@ AI Console Agent is in early development. While functional, it may have bugs or
86227
Upcoming features:
87228

88229
- Continuation of previous sessions and access to previous task context
89-
- Compilation into a single, easy-to-distribute binary
90230
- Enhanced learning and adaptation capabilities
91231
- More advanced context-aware processing
92232
- Comprehensive error handling and recovery system
@@ -105,4 +245,4 @@ If you encounter any problems or have any questions, please open an issue on the
105245

106246
## Version
107247

108-
Current version: 0.1.0
248+
Current version: 0.2.0

build.ts

+60
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
import { spawnSync } from "child_process";
2+
import fs from "fs";
3+
import path from "path";
4+
5+
const PROJECT_ROOT = process.cwd();
6+
const DIST_DIR = path.join(PROJECT_ROOT, "dist");
7+
const MAIN_FILE = path.join(PROJECT_ROOT, "src", "index.ts");
8+
const OUTPUT_FILE = path.join(DIST_DIR, "ai-console-agent");
9+
10+
async function build() {
11+
checkBunVersion();
12+
13+
console.log("Starting build process...");
14+
15+
if (!fs.existsSync(DIST_DIR)) {
16+
fs.mkdirSync(DIST_DIR);
17+
}
18+
19+
console.log("Installing dependencies...");
20+
spawnSync("bun", ["install"], { stdio: "inherit" });
21+
22+
console.log("Compiling project...");
23+
const result = spawnSync(
24+
"bun",
25+
[
26+
"build",
27+
MAIN_FILE,
28+
"--compile",
29+
"--minify",
30+
"--outfile",
31+
OUTPUT_FILE,
32+
"--target",
33+
"bun",
34+
"--format",
35+
"esm",
36+
],
37+
{ stdio: "inherit" },
38+
);
39+
40+
if (result.status !== 0) {
41+
console.error("Compilation failed");
42+
process.exit(1);
43+
}
44+
45+
console.log(`Build completed successfully. Executable: ${OUTPUT_FILE}`);
46+
}
47+
48+
function checkBunVersion() {
49+
const result = spawnSync("bun", ["--version"], { encoding: "utf8" });
50+
const version = result.stdout.trim();
51+
const requiredVersion = "1.1.30";
52+
53+
if (version !== requiredVersion) {
54+
console.warn(
55+
`Warning: This project is tested with Bun version ${requiredVersion}. You are using ${version}.`,
56+
);
57+
}
58+
}
59+
60+
build().catch(console.error);

bun.lockb

24.8 KB
Binary file not shown.

package.json

+12-2
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,27 @@
11
{
22
"name": "ai-console-agent",
3+
"version": "0.2.0",
4+
"engines": {
5+
"bun": "1.1.30"
6+
},
37
"module": "index.ts",
48
"type": "module",
9+
"scripts": {
10+
"build": "bun run build.ts"
11+
},
512
"devDependencies": {
6-
"@types/bun": "latest"
13+
"@types/bun": "latest",
14+
"@xenova/transformers": "^2.17.2",
15+
"pg": "^8.13.0",
16+
"pgvector": "^0.2.0"
717
},
818
"peerDependencies": {
919
"typescript": "^5.0.0"
1020
},
1121
"dependencies": {
1222
"chalk": "^5.3.0",
1323
"dotenv": "^16.0.0",
14-
"llamaindex": "0.6"
24+
"llamaindex": "^0.6.18"
1525
},
1626
"trustedDependencies": [
1727
"protobufjs"

src/index.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import { MAX_INPUT_LENGTH } from "./constants";
77
config();
88

99
async function main() {
10-
const { input } = parseArguments(process.argv);
10+
const { input } = parseArguments(Bun.argv);
1111

1212
if (input) {
1313
console.log(chalk.cyan(`Input: ${input}`));

src/tools/executeCommand.ts

+8-3
Original file line numberDiff line numberDiff line change
@@ -42,12 +42,17 @@ export const executeCommandTool = new FunctionTool(
4242
if (useTmux) {
4343
result = await TmuxWrapper.run(command, interactions);
4444
} else {
45-
const { stdout, stderr } = await runShellCommand(command);
46-
result = stdout + (stderr ? `\nError: ${stderr}` : "");
45+
try {
46+
const { stdout, stderr } = await runShellCommand(command, { shell: "bash" });
47+
result = JSON.stringify({ stdout, stderr });
48+
} catch (error) {
49+
console.error(chalk.red("Error in tool executing command:"), error);
50+
return { stderr: error instanceof Error ? error.message : String(error) };
51+
}
4752
}
4853

4954
console.log(
50-
chalk.green(`Successfully completed command "${command}"`) + chalk.gray(`\nResult: "${result}"`),
55+
chalk.green(`Successfully completed command "${command}"`) + chalk.gray(`\nResult:\n"${result}"`),
5156
);
5257
return result;
5358
} catch (error: unknown) {

src/utils/runShellCommand.ts

+8-5
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,14 @@ export async function runShellCommand(
99
): Promise<{ stdout: string; stderr: string }> {
1010
try {
1111
const { stdout, stderr } = await execAsync(command, options);
12-
return { stdout, stderr };
12+
return {
13+
stdout: stdout.toString(),
14+
stderr: stderr.toString(),
15+
};
1316
} catch (error: any) {
14-
console.error(`Error executing command: ${command}`, error);
15-
throw new Error(
16-
`Failed to execute command safely: ${error instanceof Error ? error.message : String(error)}`,
17-
);
17+
return {
18+
stderr: error instanceof Error ? error.message : String(error),
19+
stdout: "",
20+
};
1821
}
1922
}

tsconfig.json

+13-20
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,20 @@
11
{
22
"compilerOptions": {
3-
// Enable latest features
4-
"lib": ["ESNext", "DOM"],
53
"target": "ESNext",
64
"module": "ESNext",
7-
"moduleDetection": "force",
8-
"jsx": "react-jsx",
9-
"allowJs": true,
10-
11-
// Bundler mode
125
"moduleResolution": "bundler",
13-
"allowImportingTsExtensions": true,
14-
"verbatimModuleSyntax": true,
15-
"noEmit": true,
16-
17-
// Best practices
18-
"strict": true,
6+
"esModuleInterop": true,
197
"skipLibCheck": true,
20-
"noFallthroughCasesInSwitch": true,
21-
22-
// Some stricter flags (disabled by default)
23-
"noUnusedLocals": false,
24-
"noUnusedParameters": false,
25-
"noPropertyAccessFromIndexSignature": false
26-
}
8+
"noEmit": true,
9+
"allowJs": true,
10+
"ignoreDeprecations": "5.0",
11+
"isolatedModules": true,
12+
"resolveJsonModule": true,
13+
"forceConsistentCasingInFileNames": true,
14+
"strict": false,
15+
"strictNullChecks": true,
16+
"allowSyntheticDefaultImports": true
17+
},
18+
"include": ["src/**/*"],
19+
"exclude": ["node_modules"]
2720
}

0 commit comments

Comments
 (0)