Macos bundler .pkg
Adding .pkg bundling for mac to avoid permission problems
frdel committed
Oct 18, 2024 at 11:05 UTC
a300abc67a998ebfb7bf56c78cfc690c0e7c7fa6
5 files changed
+171
-71
.gitignore
+3
-1
@@ -10,7 +10,9 @@
10
.venv/
11
12
# ignore all folders under /bundle
13
-/bundle/*/
13
+bundle/*/
14
+# except some
15
+!bundle/mac_pkg_scripts
16
17
# Ignore all contents of the directory "work_dir"
18
work_dir/*
bundle/bundle.py
+40
-4
@@ -7,7 +7,8 @@ from pathlib import Path
7
import pathspec
8
import importlib
9
import importlib.metadata as metadata
10
-import py7zr # New import for 7z compression
10
+import py7zr
11
+import zipfile
12
13
def get_package_data_folder(package_name):
14
"""Return the package path if it contains data files."""
@@ -77,6 +78,38 @@ def cleanup_directories(bundle_name, build_dir, dist_dir, keep_dist=False):
78
if os.path.exists(spec_file):
79
os.remove(spec_file)
80
81
+def compress_internal_folder(dist_dir, exe_name):
82
+ """Compress the _internal folder using zipfile."""
83
+ try:
84
+ internal_path = Path(dist_dir) / exe_name / "_internal"
85
+ archive_path = internal_path.parent / "_internal.zip"
86
+
87
+ if not internal_path.exists():
88
+ print("Warning: _internal folder not found")
89
+ return False
90
+
91
+ # Remove existing archive if it exists
92
+ if archive_path.exists():
93
+ archive_path.unlink()
94
+
95
+ print(f"Compressing _internal folder to: {archive_path}")
96
+
97
+ # Create the zip archive
98
+ with zipfile.ZipFile(archive_path, 'w', zipfile.ZIP_STORED) as archive:
99
+ for root, dirs, files in os.walk(internal_path):
100
+ for file in files:
101
+ file_path = Path(root) / file
102
+ archive.write(file_path, arcname=file_path.relative_to(internal_path.parent))
103
+
104
+ # Remove the original _internal folder
105
+ shutil.rmtree(internal_path)
106
+ print("_internal folder compressed and removed successfully")
107
+ return True
108
+
109
+ except Exception as e:
110
+ print(f"Error during _internal compression: {e}")
111
+ return False
112
+
113
def compress_dist_folder(dist_dir, exe_name):
114
"""Compress the dist folder using py7zr library."""
115
try:
@@ -91,8 +124,8 @@ def compress_dist_folder(dist_dir, exe_name):
124
print(f"Compressing dist folder to: {archive_path}")
125
126
# Create the 7z archive with maximum compression
94
- with py7zr.SevenZipFile(archive_path, 'w', filters=[{'id': py7zr.FILTER_LZMA2, 'preset': 9}]) as archive:
95
- archive.writeall(files_path, arcname=dist_dir.name)
127
+ with py7zr.SevenZipFile(archive_path, 'w', filters=[{'id': py7zr.FILTER_LZMA2, 'preset': 2}]) as archive:
128
+ archive.writeall(files_path, arcname=files_path.name)
129
130
print("Compression completed successfully")
131
return str(archive_path)
@@ -172,6 +205,9 @@ def build_executable(script_path, exe_name=None, compress=False):
205
print(f"Executable created at: '{dist_dir}/{exe_name}'")
206
print(f"Project files copied to: '{project_files_dir}'")
207
208
+ # Compress the _internal folder first
209
+ # compress_internal_folder(dist_dir, exe_name)
210
+
211
# Compress the dist folder if requested
212
if compress:
213
archive_path = compress_dist_folder(dist_dir, exe_name)
@@ -187,4 +223,4 @@ def build_executable(script_path, exe_name=None, compress=False):
223
print(f"Error: {e}")
224
225
if __name__ == "__main__":
190
- build_executable("../run_bundle.py", "agent-zero", compress=True)
\ No newline at end of file
226
+ build_executable("../run_bundle.py", "agent-zero", compress=False)
\ No newline at end of file
bundle/mac_pkg_scripts/postinstall
new
+36
@@ -0,0 +1,36 @@
1
+#!/bin/bash
2
+
3
+# Prompt the user to select a folder using an AppleScript dialog
4
+TARGET_FOLDER=$(osascript <<EOT
5
+ tell application "System Events"
6
+ activate
7
+ set chosenFolder to choose folder with prompt "Please select a folder for the installation:"
8
+ return POSIX path of chosenFolder
9
+ end tell
10
+EOT
11
+)
12
+
13
+# Check if the user selected a folder
14
+if [ -n "$TARGET_FOLDER" ]; then
15
+ echo "Installing files to $TARGET_FOLDER"
16
+
17
+ # Move the installed files to the selected folder
18
+ mv /tmp/agent-zero/* "$TARGET_FOLDER"
19
+
20
+ # Check if the move operation was successful
21
+ if [ $? -eq 0 ]; then
22
+ echo "Files successfully moved to $TARGET_FOLDER"
23
+
24
+ # Remove the /tmp/agent-zero folder
25
+ rm -rf /tmp/agent-zero
26
+ echo "/tmp/agent-zero folder removed."
27
+ else
28
+ echo "Error moving files. Exiting."
29
+ exit 1
30
+ fi
31
+else
32
+ echo "No folder selected. Exiting installation."
33
+ exit 1
34
+fi
35
+
36
+exit 0
\ No newline at end of file
bundle/macos_bundle.sh
+26
-14
@@ -38,8 +38,8 @@ if [ -d "agent-zero" ]; then
38
fi
39
40
# 4. Clone the repository (development branch)
41
-echo "Cloning the repository (testing branch)..."
42
-git clone --branch testing https://github.com/frdel/agent-zero agent-zero
41
+echo "Cloning the repository (development branch)..."
42
+git clone --branch development https://github.com/frdel/agent-zero agent-zero
43
if [ $? -ne 0 ]; then
44
echo "Error cloning the repository."
45
exit 1
@@ -67,18 +67,30 @@ if [ $? -ne 0 ]; then
67
exit 1
68
fi
69
70
-# 9. Move the generated 7z file to the script directory and remove agent-zero folder
71
-BUNDLE_FILE="bundle/dist/agent-zero.7z"
72
-if [ -f "$BUNDLE_FILE" ]; then
73
- SCRIPT_DIR=$(dirname "$0")
74
- echo "Moving $BUNDLE_FILE to $SCRIPT_DIR..."
75
- mv "$BUNDLE_FILE" "$SCRIPT_DIR"
76
- if [ $? -ne 0 ]; then
77
- echo "Error moving $BUNDLE_FILE to $SCRIPT_DIR."
78
- exit 1
79
- fi
80
-else
81
- echo "Error: $BUNDLE_FILE not found."
70
+# # 9. Move the generated 7z file to the script directory and remove agent-zero folder
71
+# BUNDLE_FILE="bundle/dist/agent-zero.7z"
72
+# if [ -f "$BUNDLE_FILE" ]; then
73
+# SCRIPT_DIR=$(dirname "$0")
74
+# echo "Moving $BUNDLE_FILE to $SCRIPT_DIR..."
75
+# mv "$BUNDLE_FILE" "$SCRIPT_DIR"
76
+# if [ $? -ne 0 ]; then
77
+# echo "Error moving $BUNDLE_FILE to $SCRIPT_DIR."
78
+# exit 1
79
+# fi
80
+# else
81
+# echo "Error: $BUNDLE_FILE not found."
82
+# exit 1
83
+# fi
84
+
85
+# 9. Create macOS package
86
+echo "Creating macOS package..."
87
+pkgbuild --root ./dist/agent-zero \
88
+ --identifier frdel.agent-zero \
89
+ --install-location /tmp/agent-zero \
90
+ --scripts ./mac_pkg_scripts \
91
+ agent-zero-preinstalled-mac-m1.pkg
92
+if [ $? -ne 0 ]; then
93
+ echo "Error creating macOS package."
94
exit 1
95
fi
96
run_bundle.py
+66
-52
@@ -1,64 +1,78 @@
1
-print("\nImporting dependencies, this may take a while...\n")
1
+def post_install():
2
+ # if "_internal.zip" exists, unzip and remove
3
+ import os
4
+ if os.path.exists("_internal.zip"):
5
+ import zipfile
6
+ print("\nDecompressing internal binaries...\n")
7
+ with zipfile.ZipFile("_internal.zip", 'r') as zip_ref:
8
+ zip_ref.extractall("_internal")
9
+ os.remove("_internal.zip")
10
+
11
+def run_bundle():
12
+ print("\nImporting dependencies, this may take a while...\n")
13
+
14
+ # dependencies to bundle
15
+ import ansio
16
+ import bs4
17
+ import docker
18
+ import duckduckgo_search
19
+ import faiss
20
+ from flask import Flask
21
+ import flask_basicauth
22
+ import inputimeout
23
+ import langchain.embeddings
24
+ import langchain_anthropic
25
+ import langchain_community
26
+ import langchain_google_genai
27
+ import langchain_groq
28
+ import langchain_huggingface
29
+ import langchain_mistralai
30
+ import langchain_ollama
31
+ import langchain_openai
32
+ import lxml_html_clean
33
+ import emoji
34
+ from emoji import unicode_codes
35
+ import markdown
36
+ import newspaper
37
+ import paramiko
38
+ import pypdf
39
+ import dotenv
40
+ import sentence_transformers
41
+ from tiktoken import model, registry
42
+ from tiktoken_ext import openai_public
43
+ import unstructured
44
+ import unstructured_client
45
+ import webcolors
46
47
4
-# dependencies to bundle
5
-import ansio
6
-import bs4
7
-import docker
8
-import duckduckgo_search
9
-import faiss
10
-from flask import Flask
11
-import flask_basicauth
12
-import inputimeout
13
-import langchain.embeddings
14
-import langchain_anthropic
15
-import langchain_community
16
-import langchain_google_genai
17
-import langchain_groq
18
-import langchain_huggingface
19
-import langchain_mistralai
20
-import langchain_ollama
21
-import langchain_openai
22
-import lxml_html_clean
23
-import emoji
24
-from emoji import unicode_codes
25
-import markdown
26
-import newspaper
27
-import paramiko
28
-import pypdf
29
-import dotenv
30
-import sentence_transformers
31
-from tiktoken import model, registry
32
-from tiktoken_ext import openai_public
33
-import unstructured
34
-import unstructured_client
35
-import webcolors
48
49
+ # but do not bundle project files, these are to be imported at runtime
50
51
39
-# but do not bundle project files, these are to be imported at runtime
52
53
+ import sys
54
+ import os
55
+ import importlib.util
56
57
+ # Add the project_files directory to the Python path
58
+ project_files_dir = os.path.join(os.path.dirname(sys.executable), 'agent-zero-files')
59
+ sys.path.insert(0, project_files_dir)
60
43
-import sys
44
-import os
45
-import importlib.util
61
+ # Dynamically load the 'run_ui' module
62
+ module_name = "run_ui"
63
+ module_path = os.path.join(project_files_dir, f"{module_name}.py")
64
47
-# Add the project_files directory to the Python path
48
-project_files_dir = os.path.join(os.path.dirname(sys.executable), 'agent-zero-files')
49
-sys.path.insert(0, project_files_dir)
65
+ # Load the module at runtime
66
+ spec = importlib.util.spec_from_file_location(module_name, module_path)
67
+ if spec and spec.loader:
68
+ run_ui = importlib.util.module_from_spec(spec)
69
+ spec.loader.exec_module(run_ui)
70
51
-# Dynamically load the 'run_ui' module
52
-module_name = "run_ui"
53
-module_path = os.path.join(project_files_dir, f"{module_name}.py")
71
+ # Now you can call the function in the dynamically imported module
72
+ run_ui.run() # Call the 'run' function from run_ui
73
+ else:
74
+ raise Exception(f"Could not load {module_name} from {module_path}")
75
55
-# Load the module at runtime
56
-spec = importlib.util.spec_from_file_location(module_name, module_path)
57
-if spec and spec.loader:
58
- run_ui = importlib.util.module_from_spec(spec)
59
- spec.loader.exec_module(run_ui)
76
61
- # Now you can call the function in the dynamically imported module
62
- run_ui.run() # Call the 'run' function from run_ui
63
-else:
64
- raise Exception(f"Could not load {module_name} from {module_path}")
\ No newline at end of file
77
+# post_install()
78
+run_bundle()
\ No newline at end of file