abstractassistant 0.2.5__py3-none-any.whl → 0.2.7__py3-none-any.whl

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.
@@ -0,0 +1,53 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ Create macOS App Bundle for AbstractAssistant.
4
+
5
+ This script can be run after installation to create a macOS app bundle
6
+ that allows launching AbstractAssistant from the Dock.
7
+ """
8
+
9
+ import sys
10
+ from pathlib import Path
11
+
12
+
13
+ def main():
14
+ """Create macOS app bundle for AbstractAssistant."""
15
+ try:
16
+ # Import the app bundle generator
17
+ try:
18
+ import setup_macos_app
19
+ MacOSAppBundleGenerator = setup_macos_app.MacOSAppBundleGenerator
20
+ except ImportError:
21
+ # Fallback: try importing from abstractassistant package
22
+ from abstractassistant.setup_macos_app import MacOSAppBundleGenerator
23
+
24
+ # Find the package directory
25
+ import abstractassistant
26
+ package_dir = Path(abstractassistant.__file__).parent
27
+
28
+ # Create the generator and build the app bundle
29
+ generator = MacOSAppBundleGenerator(package_dir)
30
+
31
+ print("🍎 Creating macOS app bundle for AbstractAssistant...")
32
+ success = generator.generate_app_bundle()
33
+
34
+ if success:
35
+ print("\n🎉 Success!")
36
+ print(" AbstractAssistant is now available in your Applications folder")
37
+ print(" You can launch it from the Dock or Spotlight!")
38
+ return 0
39
+ else:
40
+ print("\n❌ Failed to create app bundle")
41
+ return 1
42
+
43
+ except ImportError as e:
44
+ print(f"❌ Error: {e}")
45
+ print(" Make sure AbstractAssistant is properly installed")
46
+ return 1
47
+ except Exception as e:
48
+ print(f"❌ Unexpected error: {e}")
49
+ return 1
50
+
51
+
52
+ if __name__ == "__main__":
53
+ sys.exit(main())
@@ -1,16 +1,15 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: abstractassistant
3
- Version: 0.2.5
3
+ Version: 0.2.7
4
4
  Summary: A sleek (macOS) system tray application providing instant access to LLMs
5
5
  Author-email: Laurent-Philippe Albou <contact@abstractcore.ai>
6
- License: MIT
6
+ License-Expression: MIT
7
7
  Project-URL: Homepage, https://github.com/lpalbou/abstractassistant
8
8
  Project-URL: Repository, https://github.com/lpalbou/abstractassistant
9
9
  Project-URL: Issues, https://github.com/lpalbou/abstractassistant/issues
10
10
  Keywords: ai,llm,macos,system-tray,assistant
11
11
  Classifier: Development Status :: 4 - Beta
12
12
  Classifier: Intended Audience :: End Users/Desktop
13
- Classifier: License :: OSI Approved :: MIT License
14
13
  Classifier: Operating System :: MacOS
15
14
  Classifier: Programming Language :: Python :: 3
16
15
  Classifier: Programming Language :: Python :: 3.9
@@ -67,17 +66,46 @@ A sleek macOS system tray application providing instant access to Large Language
67
66
  ## 🚀 Quick Start
68
67
 
69
68
  ### 1. Installation
69
+
70
+ #### 🍎 macOS Users (Recommended)
71
+ ```bash
72
+ # Enhanced installation with Dock integration
73
+ python3 install.py
74
+ ```
75
+
76
+ This will:
77
+ - Install AbstractAssistant from PyPI
78
+ - Create a macOS app bundle in `/Applications`
79
+ - Add AbstractAssistant to your Dock for easy access
80
+
81
+ **Alternative**: After installation, create the app bundle manually:
82
+ ```bash
83
+ pip install abstractassistant
84
+ create-app-bundle
85
+ ```
86
+
87
+ #### 🔧 Standard Installation
70
88
  ```bash
71
- # Install from PyPI (recommended)
89
+ # Install from PyPI
72
90
  pip install abstractassistant
73
91
  ```
74
92
 
75
93
  For detailed installation instructions including prerequisites and voice setup, see **[📖 Installation Guide](docs/installation.md)**.
76
94
 
77
95
  ### 2. First Launch
96
+
97
+ #### 🍎 macOS App Bundle Users
98
+ - **Dock**: Click the AbstractAssistant icon in your Dock
99
+ - **Spotlight**: Search for "AbstractAssistant" and press Enter
100
+ - **Finder**: Open `/Applications/AbstractAssistant.app`
101
+
102
+ #### 🔧 Terminal Users
78
103
  ```bash
79
104
  # Launch the assistant
80
105
  assistant
106
+
107
+ # Create macOS app bundle after installation
108
+ create-app-bundle
81
109
  ```
82
110
 
83
111
  ### 3. Start Using
@@ -1,7 +1,9 @@
1
+ setup_macos_app.py,sha256=PP-X7UVfv8VmwaOtmNao0Bn3P5oXRAgfs13TXMpNhA8,8806
1
2
  abstractassistant/__init__.py,sha256=homfqMDh6sX2nBROtk6-y72jnrStPph8gEOeT0OjKyU,35
2
3
  abstractassistant/app.py,sha256=-Nkgj1IruGhiuyMt7-EQPBwxXoeIykaO1FYKlS520zA,34032
3
4
  abstractassistant/cli.py,sha256=SQPxQCLjX-LOlhSEvG302D0AOyxlxo5QM2imxr9wxmc,4385
4
5
  abstractassistant/config.py,sha256=KodfPYTpHtavJyne-h-B-r3kbEt1uusSY8GknGLtDL8,5809
6
+ abstractassistant/create_app_bundle.py,sha256=LAZdp2C90ikMVd3KPdwNYBYUASbHpypOJIwvx6fQyXM,1698
5
7
  abstractassistant/web_server.py,sha256=_pqMzy13qfim9BMBqQJQifWyX7UQXFD_sZeiu4ZBt40,12816
6
8
  abstractassistant/core/__init__.py,sha256=TETStgToTe7QSsCZgRHDk2oSErlLJoeGN0sFg4Yx2_c,15
7
9
  abstractassistant/core/llm_manager.py,sha256=yIvFj0pSLeC22PsaD0a3I4PjylO5Qvju8P_1e9iyXAM,11376
@@ -18,9 +20,9 @@ abstractassistant/ui/ui_styles.py,sha256=VoGlrZI3YJzDKPv9LWz39W3XcFI4N952rkzXb8M
18
20
  abstractassistant/utils/__init__.py,sha256=7Q3BxyXETkt3tm5trhuLTyL8PoECOK0QiK-0KUVAR2Q,16
19
21
  abstractassistant/utils/icon_generator.py,sha256=MH3giercjE6Dh100EZ_8kw5WC0PVwd5F4inKfRDLp2w,10455
20
22
  abstractassistant/utils/markdown_renderer.py,sha256=sTn045glqxh5QU3LIuYp7zQpBIuwf5e3cWZzDz5i0Yw,12620
21
- abstractassistant-0.2.5.dist-info/licenses/LICENSE,sha256=QUjFNAE-0yOkW9-Rle2axkpkt9H7xiZ2VbN-VeONhxc,1106
22
- abstractassistant-0.2.5.dist-info/METADATA,sha256=0Zo6V7ql9bNfWcExMQSoqyNh6g1xGfwOqcYMU4bNYT4,10607
23
- abstractassistant-0.2.5.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
24
- abstractassistant-0.2.5.dist-info/entry_points.txt,sha256=hSNmsf88uDC7eDA2yeTK17IFz5MtaPZEx5_0jQJ2aAY,57
25
- abstractassistant-0.2.5.dist-info/top_level.txt,sha256=qZc_LQH3CBxLq2P4B1aHayzkj8hn0euR31edkXQVzDA,18
26
- abstractassistant-0.2.5.dist-info/RECORD,,
23
+ abstractassistant-0.2.7.dist-info/licenses/LICENSE,sha256=QUjFNAE-0yOkW9-Rle2axkpkt9H7xiZ2VbN-VeONhxc,1106
24
+ abstractassistant-0.2.7.dist-info/METADATA,sha256=oE3-3e4BiaeEFEYv6q7yHiUG45aAGnwcFHZ3SUhdH7A,11283
25
+ abstractassistant-0.2.7.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
26
+ abstractassistant-0.2.7.dist-info/entry_points.txt,sha256=MIzeCh0XG6MbhIzBHtkdEjmjxYBsQrGFevq8Y1L8Jkc,118
27
+ abstractassistant-0.2.7.dist-info/top_level.txt,sha256=oEcSXZAqbflTfZRfF4dogUq6TC1Nqyplq4JgC0CZnLI,34
28
+ abstractassistant-0.2.7.dist-info/RECORD,,
@@ -0,0 +1,3 @@
1
+ [console_scripts]
2
+ assistant = abstractassistant.cli:main
3
+ create-app-bundle = abstractassistant.create_app_bundle:main
@@ -1 +1,2 @@
1
1
  abstractassistant
2
+ setup_macos_app
setup_macos_app.py ADDED
@@ -0,0 +1,269 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ macOS App Bundle Generator for AbstractAssistant.
4
+
5
+ This module creates a macOS .app bundle during installation,
6
+ allowing users to launch AbstractAssistant from the Dock.
7
+ """
8
+
9
+ import os
10
+ import sys
11
+ import shutil
12
+ import subprocess
13
+ from pathlib import Path
14
+ from typing import Optional
15
+
16
+ try:
17
+ from PIL import Image
18
+ PIL_AVAILABLE = True
19
+ except ImportError:
20
+ PIL_AVAILABLE = False
21
+
22
+
23
+ class MacOSAppBundleGenerator:
24
+ """Generates macOS app bundles for AbstractAssistant."""
25
+
26
+ def __init__(self, package_dir: Path):
27
+ """Initialize the app bundle generator.
28
+
29
+ Args:
30
+ package_dir: Path to the abstractassistant package directory
31
+ """
32
+ self.package_dir = package_dir
33
+ self.app_name = "AbstractAssistant"
34
+ self.app_bundle_path = Path("/Applications") / f"{self.app_name}.app"
35
+
36
+ def is_macos(self) -> bool:
37
+ """Check if running on macOS."""
38
+ return sys.platform == "darwin"
39
+
40
+ def has_permissions(self) -> bool:
41
+ """Check if we have permissions to write to /Applications."""
42
+ try:
43
+ test_file = Path("/Applications") / ".test_write_permission"
44
+ test_file.touch()
45
+ test_file.unlink()
46
+ return True
47
+ except (PermissionError, OSError):
48
+ return False
49
+
50
+ def create_app_bundle_structure(self) -> bool:
51
+ """Create the basic app bundle directory structure."""
52
+ try:
53
+ # Create main directories
54
+ contents_dir = self.app_bundle_path / "Contents"
55
+ macos_dir = contents_dir / "MacOS"
56
+ resources_dir = contents_dir / "Resources"
57
+
58
+ for directory in [contents_dir, macos_dir, resources_dir]:
59
+ directory.mkdir(parents=True, exist_ok=True)
60
+
61
+ return True
62
+ except Exception as e:
63
+ print(f"Error creating app bundle structure: {e}")
64
+ return False
65
+
66
+ def generate_app_icon(self) -> bool:
67
+ """Generate the app icon using the existing icon generator."""
68
+ try:
69
+ # Import the icon generator
70
+ sys.path.insert(0, str(self.package_dir))
71
+ from abstractassistant.utils.icon_generator import IconGenerator
72
+
73
+ # Generate high-resolution icon
74
+ generator = IconGenerator(size=512)
75
+ icon = generator.create_app_icon('blue', animated=False)
76
+
77
+ # Save as PNG
78
+ icon_path = self.app_bundle_path / "Contents" / "Resources" / "icon.png"
79
+ icon.save(str(icon_path))
80
+
81
+ # Create ICNS file
82
+ return self._create_icns_file(icon_path)
83
+
84
+ except Exception as e:
85
+ print(f"Error generating app icon: {e}")
86
+ return False
87
+
88
+ def _create_icns_file(self, png_path: Path) -> bool:
89
+ """Create ICNS file from PNG using macOS iconutil."""
90
+ try:
91
+ # Create iconset directory
92
+ iconset_dir = png_path.parent / "temp_icons.iconset"
93
+ iconset_dir.mkdir(exist_ok=True)
94
+
95
+ # Load the PNG and create different sizes
96
+ icon = Image.open(png_path)
97
+ sizes = [
98
+ (16, 'icon_16x16.png'),
99
+ (32, 'icon_16x16@2x.png'),
100
+ (32, 'icon_32x32.png'),
101
+ (64, 'icon_32x32@2x.png'),
102
+ (128, 'icon_128x128.png'),
103
+ (256, 'icon_128x128@2x.png'),
104
+ (256, 'icon_256x256.png'),
105
+ (512, 'icon_256x256@2x.png'),
106
+ (512, 'icon_512x512.png'),
107
+ (1024, 'icon_512x512@2x.png')
108
+ ]
109
+
110
+ for size, filename in sizes:
111
+ resized = icon.resize((size, size), Image.Resampling.LANCZOS)
112
+ resized.save(iconset_dir / filename)
113
+
114
+ # Convert to ICNS
115
+ icns_path = png_path.parent / "icon.icns"
116
+ result = subprocess.run([
117
+ 'iconutil', '-c', 'icns', str(iconset_dir),
118
+ '-o', str(icns_path)
119
+ ], capture_output=True, text=True)
120
+
121
+ # Clean up
122
+ shutil.rmtree(iconset_dir)
123
+
124
+ return result.returncode == 0
125
+
126
+ except Exception as e:
127
+ print(f"Error creating ICNS file: {e}")
128
+ return False
129
+
130
+ def create_info_plist(self) -> bool:
131
+ """Create the Info.plist file."""
132
+ try:
133
+ plist_content = '''<?xml version="1.0" encoding="UTF-8"?>
134
+ <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
135
+ <plist version="1.0">
136
+ <dict>
137
+ <key>CFBundleExecutable</key>
138
+ <string>AbstractAssistant</string>
139
+ <key>CFBundleIdentifier</key>
140
+ <string>ai.abstractcore.abstractassistant</string>
141
+ <key>CFBundleName</key>
142
+ <string>AbstractAssistant</string>
143
+ <key>CFBundleDisplayName</key>
144
+ <string>AbstractAssistant</string>
145
+ <key>CFBundleVersion</key>
146
+ <string>0.2.5</string>
147
+ <key>CFBundleShortVersionString</key>
148
+ <string>0.2.5</string>
149
+ <key>CFBundlePackageType</key>
150
+ <string>APPL</string>
151
+ <key>CFBundleSignature</key>
152
+ <string>????</string>
153
+ <key>CFBundleIconFile</key>
154
+ <string>icon.icns</string>
155
+ <key>LSMinimumSystemVersion</key>
156
+ <string>10.15</string>
157
+ <key>NSHighResolutionCapable</key>
158
+ <true/>
159
+ <key>NSRequiresAquaSystemAppearance</key>
160
+ <false/>
161
+ <key>LSUIElement</key>
162
+ <true/>
163
+ <key>NSAppleScriptEnabled</key>
164
+ <false/>
165
+ <key>CFBundleDocumentTypes</key>
166
+ <array/>
167
+ <key>NSPrincipalClass</key>
168
+ <string>NSApplication</string>
169
+ </dict>
170
+ </plist>'''
171
+
172
+ plist_path = self.app_bundle_path / "Contents" / "Info.plist"
173
+ plist_path.write_text(plist_content)
174
+ return True
175
+
176
+ except Exception as e:
177
+ print(f"Error creating Info.plist: {e}")
178
+ return False
179
+
180
+ def create_launch_script(self) -> bool:
181
+ """Create the executable launch script."""
182
+ try:
183
+ script_content = '''#!/bin/bash
184
+
185
+ # AbstractAssistant macOS App Launcher
186
+ # This script launches the AbstractAssistant application
187
+
188
+ # Find the Python executable and package
189
+ PYTHON_EXEC="$(which python3)"
190
+ if [ -z "$PYTHON_EXEC" ]; then
191
+ PYTHON_EXEC="$(which python)"
192
+ fi
193
+
194
+ if [ -z "$PYTHON_EXEC" ]; then
195
+ echo "Error: Python not found in PATH"
196
+ exit 1
197
+ fi
198
+
199
+ # Launch the assistant
200
+ exec "$PYTHON_EXEC" -m abstractassistant.cli "$@"'''
201
+
202
+ script_path = self.app_bundle_path / "Contents" / "MacOS" / "AbstractAssistant"
203
+ script_path.write_text(script_content)
204
+
205
+ # Make executable
206
+ os.chmod(script_path, 0o755)
207
+ return True
208
+
209
+ except Exception as e:
210
+ print(f"Error creating launch script: {e}")
211
+ return False
212
+
213
+ def generate_app_bundle(self) -> bool:
214
+ """Generate the complete macOS app bundle."""
215
+ if not self.is_macos():
216
+ print("macOS app bundle generation is only available on macOS")
217
+ return False
218
+
219
+ if not self.has_permissions():
220
+ print("Insufficient permissions to create app bundle in /Applications")
221
+ print("Please run with sudo or manually copy the app bundle")
222
+ return False
223
+
224
+ print("Creating macOS app bundle...")
225
+
226
+ # Remove existing bundle if it exists
227
+ if self.app_bundle_path.exists():
228
+ shutil.rmtree(self.app_bundle_path)
229
+
230
+ # Create bundle structure
231
+ if not self.create_app_bundle_structure():
232
+ return False
233
+
234
+ # Generate icon
235
+ if not self.generate_app_icon():
236
+ return False
237
+
238
+ # Create Info.plist
239
+ if not self.create_info_plist():
240
+ return False
241
+
242
+ # Create launch script
243
+ if not self.create_launch_script():
244
+ return False
245
+
246
+ print(f"✅ macOS app bundle created successfully!")
247
+ print(f" Location: {self.app_bundle_path}")
248
+ print(f" You can now launch AbstractAssistant from the Dock!")
249
+
250
+ return True
251
+
252
+
253
+ def create_macos_app_bundle():
254
+ """Main function to create macOS app bundle during installation."""
255
+ try:
256
+ # Find the package directory
257
+ package_dir = Path(__file__).parent
258
+
259
+ generator = MacOSAppBundleGenerator(package_dir)
260
+ return generator.generate_app_bundle()
261
+
262
+ except Exception as e:
263
+ print(f"Error creating macOS app bundle: {e}")
264
+ return False
265
+
266
+
267
+ if __name__ == "__main__":
268
+ success = create_macos_app_bundle()
269
+ sys.exit(0 if success else 1)
@@ -1,2 +0,0 @@
1
- [console_scripts]
2
- assistant = abstractassistant.cli:main