aegis-framework 0.1.1 → 0.1.2
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 +44 -0
- package/aegis/core/__pycache__/window.cpython-312.pyc +0 -0
- package/aegis/core/window.py +104 -13
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -181,7 +181,51 @@ console.log(result.output);
|
|
|
181
181
|
// Python code
|
|
182
182
|
const py = await Aegis.run({ py: '2 + 2' });
|
|
183
183
|
console.log(py.output); // "4"
|
|
184
|
+
|
|
185
|
+
// Async command with streaming output (UI won't freeze!)
|
|
186
|
+
await Aegis.runAsync(
|
|
187
|
+
{ sh: 'apt update' },
|
|
188
|
+
(progress) => console.log(progress.line)
|
|
189
|
+
);
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
### Downloads (with aria2c turbo mode!)
|
|
193
|
+
|
|
194
|
+
Aegis uses **aria2c** for blazing fast downloads with multiple connections:
|
|
195
|
+
|
|
196
|
+
```javascript
|
|
197
|
+
// Basic download with progress
|
|
198
|
+
await Aegis.download(
|
|
199
|
+
{
|
|
200
|
+
url: 'https://example.com/large-file.zip',
|
|
201
|
+
dest: '/home/user/downloads/file.zip'
|
|
202
|
+
},
|
|
203
|
+
(progress) => {
|
|
204
|
+
console.log(`${progress.percent.toFixed(1)}%`);
|
|
205
|
+
console.log(`Speed: ${progress.speed}`); // "5.2 MiB/s"
|
|
206
|
+
console.log(`Engine: ${progress.engine}`); // "aria2c" or "urllib"
|
|
207
|
+
}
|
|
208
|
+
);
|
|
209
|
+
|
|
210
|
+
// Turbo mode with 16 connections (for fast internet)
|
|
211
|
+
await Aegis.download(
|
|
212
|
+
{
|
|
213
|
+
url: 'https://example.com/game.iso',
|
|
214
|
+
dest: '/home/user/games/game.iso',
|
|
215
|
+
connections: 16 // Up to 16 simultaneous connections!
|
|
216
|
+
},
|
|
217
|
+
(progress) => {
|
|
218
|
+
progressBar.style.width = progress.percent + '%';
|
|
219
|
+
speedLabel.textContent = progress.speed;
|
|
220
|
+
}
|
|
221
|
+
);
|
|
222
|
+
```
|
|
223
|
+
|
|
224
|
+
**Note:** For maximum speed, install aria2c:
|
|
225
|
+
```bash
|
|
226
|
+
sudo apt install aria2
|
|
184
227
|
```
|
|
228
|
+
If aria2c is not installed, Aegis automatically falls back to standard downloads.
|
|
185
229
|
|
|
186
230
|
## 🔒 Security (preload.js)
|
|
187
231
|
|
|
Binary file
|
package/aegis/core/window.py
CHANGED
|
@@ -677,45 +677,136 @@ class AegisWindow(Gtk.Window):
|
|
|
677
677
|
GLib.idle_add(self._send_error, callback_id, str(e))
|
|
678
678
|
|
|
679
679
|
def _handle_download(self, payload, callback_id):
|
|
680
|
-
"""Download file with progress updates"""
|
|
680
|
+
"""Download file with progress updates - uses aria2c if available for faster downloads"""
|
|
681
|
+
url = payload.get('url')
|
|
682
|
+
dest = payload.get('dest')
|
|
683
|
+
connections = payload.get('connections', 8) # Max simultaneous connections
|
|
684
|
+
|
|
681
685
|
try:
|
|
682
|
-
|
|
683
|
-
dest
|
|
686
|
+
# Ensure destination directory exists
|
|
687
|
+
os.makedirs(os.path.dirname(dest) or '.', exist_ok=True)
|
|
688
|
+
|
|
689
|
+
# Check if aria2c is available for faster downloads
|
|
690
|
+
if shutil.which('aria2c'):
|
|
691
|
+
self._download_with_aria2(url, dest, connections, callback_id)
|
|
692
|
+
else:
|
|
693
|
+
self._download_with_urllib(url, dest, callback_id)
|
|
694
|
+
|
|
695
|
+
except Exception as e:
|
|
696
|
+
GLib.idle_add(self._send_error, callback_id, str(e))
|
|
697
|
+
|
|
698
|
+
def _download_with_aria2(self, url, dest, connections, callback_id):
|
|
699
|
+
"""Download using aria2c for multi-connection speed boost"""
|
|
700
|
+
import subprocess
|
|
701
|
+
import re
|
|
702
|
+
|
|
703
|
+
try:
|
|
704
|
+
dest_dir = os.path.dirname(dest) or '.'
|
|
705
|
+
dest_file = os.path.basename(dest)
|
|
706
|
+
|
|
707
|
+
cmd = [
|
|
708
|
+
'aria2c',
|
|
709
|
+
'-x', str(connections), # Max connections per server
|
|
710
|
+
'-s', str(connections), # Split file into N parts
|
|
711
|
+
'-k', '1M', # Min split size
|
|
712
|
+
'--console-log-level=warn',
|
|
713
|
+
'--summary-interval=1',
|
|
714
|
+
'--download-result=hide',
|
|
715
|
+
'-d', dest_dir,
|
|
716
|
+
'-o', dest_file,
|
|
717
|
+
'--allow-overwrite=true',
|
|
718
|
+
url
|
|
719
|
+
]
|
|
720
|
+
|
|
721
|
+
process = subprocess.Popen(
|
|
722
|
+
cmd,
|
|
723
|
+
stdout=subprocess.PIPE,
|
|
724
|
+
stderr=subprocess.STDOUT,
|
|
725
|
+
text=True,
|
|
726
|
+
bufsize=1
|
|
727
|
+
)
|
|
684
728
|
|
|
685
|
-
|
|
729
|
+
total_size = 0
|
|
730
|
+
downloaded = 0
|
|
731
|
+
|
|
732
|
+
for line in process.stdout:
|
|
733
|
+
# Parse aria2c progress: [#abc123 1.2MiB/50MiB(2%) CN:8 DL:5.2MiB]
|
|
734
|
+
progress_match = re.search(r'\[#\w+\s+([\d.]+)(\w+)/([\d.]+)(\w+)\s*\((\d+)%\).*DL:([\d.]+)(\w+)', line)
|
|
735
|
+
if progress_match:
|
|
736
|
+
dl_num, dl_unit, total_num, total_unit, percent, speed_num, speed_unit = progress_match.groups()
|
|
737
|
+
|
|
738
|
+
# Convert to bytes
|
|
739
|
+
def to_bytes(num, unit):
|
|
740
|
+
multipliers = {'B': 1, 'KiB': 1024, 'MiB': 1024**2, 'GiB': 1024**3}
|
|
741
|
+
return float(num) * multipliers.get(unit, 1)
|
|
742
|
+
|
|
743
|
+
downloaded = int(to_bytes(dl_num, dl_unit))
|
|
744
|
+
total_size = int(to_bytes(total_num, total_unit))
|
|
745
|
+
speed = f"{speed_num} {speed_unit}/s"
|
|
746
|
+
|
|
747
|
+
progress = {
|
|
748
|
+
'downloaded': downloaded,
|
|
749
|
+
'total': total_size,
|
|
750
|
+
'percent': float(percent),
|
|
751
|
+
'speed': speed,
|
|
752
|
+
'connections': connections,
|
|
753
|
+
'engine': 'aria2c'
|
|
754
|
+
}
|
|
755
|
+
GLib.idle_add(self._send_progress, callback_id, progress)
|
|
756
|
+
|
|
757
|
+
process.wait()
|
|
758
|
+
|
|
759
|
+
if process.returncode == 0:
|
|
760
|
+
# Get final file size
|
|
761
|
+
final_size = os.path.getsize(dest) if os.path.exists(dest) else downloaded
|
|
762
|
+
result = {
|
|
763
|
+
'success': True,
|
|
764
|
+
'path': dest,
|
|
765
|
+
'size': final_size,
|
|
766
|
+
'engine': 'aria2c'
|
|
767
|
+
}
|
|
768
|
+
GLib.idle_add(self._send_response, callback_id, result)
|
|
769
|
+
else:
|
|
770
|
+
GLib.idle_add(self._send_error, callback_id, f"aria2c exited with code {process.returncode}")
|
|
771
|
+
|
|
772
|
+
except Exception as e:
|
|
773
|
+
GLib.idle_add(self._send_error, callback_id, str(e))
|
|
774
|
+
|
|
775
|
+
def _download_with_urllib(self, url, dest, callback_id):
|
|
776
|
+
"""Fallback download using urllib (single connection)"""
|
|
777
|
+
try:
|
|
686
778
|
req = urllib.request.Request(url, headers={
|
|
687
779
|
'User-Agent': 'Aegis/0.1.0'
|
|
688
780
|
})
|
|
689
781
|
|
|
690
|
-
response = urllib.request.urlopen(req, timeout=
|
|
782
|
+
response = urllib.request.urlopen(req, timeout=60)
|
|
691
783
|
total_size = int(response.headers.get('Content-Length', 0))
|
|
692
784
|
downloaded = 0
|
|
693
785
|
|
|
694
|
-
# Ensure destination directory exists
|
|
695
|
-
os.makedirs(os.path.dirname(dest) or '.', exist_ok=True)
|
|
696
|
-
|
|
697
786
|
with open(dest, 'wb') as f:
|
|
698
787
|
while True:
|
|
699
|
-
chunk = response.read(
|
|
788
|
+
chunk = response.read(65536) # 64KB chunks
|
|
700
789
|
if not chunk:
|
|
701
790
|
break
|
|
702
791
|
|
|
703
792
|
f.write(chunk)
|
|
704
793
|
downloaded += len(chunk)
|
|
705
794
|
|
|
706
|
-
# Send progress update
|
|
707
795
|
progress = {
|
|
708
796
|
'downloaded': downloaded,
|
|
709
797
|
'total': total_size,
|
|
710
|
-
'percent': (downloaded / total_size * 100) if total_size else 0
|
|
798
|
+
'percent': (downloaded / total_size * 100) if total_size else 0,
|
|
799
|
+
'speed': None,
|
|
800
|
+
'connections': 1,
|
|
801
|
+
'engine': 'urllib'
|
|
711
802
|
}
|
|
712
803
|
GLib.idle_add(self._send_progress, callback_id, progress)
|
|
713
804
|
|
|
714
|
-
# Send completion
|
|
715
805
|
result = {
|
|
716
806
|
'success': True,
|
|
717
807
|
'path': dest,
|
|
718
|
-
'size': downloaded
|
|
808
|
+
'size': downloaded,
|
|
809
|
+
'engine': 'urllib'
|
|
719
810
|
}
|
|
720
811
|
GLib.idle_add(self._send_response, callback_id, result)
|
|
721
812
|
|
package/package.json
CHANGED