netrun-ui 0.1.1__tar.gz
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.
- netrun_ui-0.1.1/.gitignore +56 -0
- netrun_ui-0.1.1/BACKEND_README.md +58 -0
- netrun_ui-0.1.1/PKG-INFO +76 -0
- netrun_ui-0.1.1/hatch_build.py +67 -0
- netrun_ui-0.1.1/netrun_ui_backend/__init__.py +1 -0
- netrun_ui-0.1.1/netrun_ui_backend/cli.py +394 -0
- netrun_ui-0.1.1/netrun_ui_backend/converter.py +370 -0
- netrun_ui-0.1.1/netrun_ui_backend/main.py +104 -0
- netrun_ui-0.1.1/netrun_ui_backend/routes/__init__.py +1 -0
- netrun_ui-0.1.1/netrun_ui_backend/routes/actions.py +279 -0
- netrun_ui-0.1.1/netrun_ui_backend/routes/factories.py +380 -0
- netrun_ui-0.1.1/netrun_ui_backend/routes/files.py +677 -0
- netrun_ui-0.1.1/package-lock.json +2022 -0
- netrun_ui-0.1.1/package.json +26 -0
- netrun_ui-0.1.1/pyproject.toml +57 -0
- netrun_ui-0.1.1/src/app.css +88 -0
- netrun_ui-0.1.1/src/app.d.ts +13 -0
- netrun_ui-0.1.1/src/app.html +11 -0
- netrun_ui-0.1.1/src/lib/api.ts +415 -0
- netrun_ui-0.1.1/src/lib/assets/favicon.svg +1 -0
- netrun_ui-0.1.1/src/lib/commands.ts +577 -0
- netrun_ui-0.1.1/src/lib/components/ActionEditor.svelte +327 -0
- netrun_ui-0.1.1/src/lib/components/ActionsPanel.svelte +368 -0
- netrun_ui-0.1.1/src/lib/components/Breadcrumb.svelte +75 -0
- netrun_ui-0.1.1/src/lib/components/CommandPalette.svelte +446 -0
- netrun_ui-0.1.1/src/lib/components/FactorySelectorModal.svelte +504 -0
- netrun_ui-0.1.1/src/lib/components/FileExplorer.svelte +359 -0
- netrun_ui-0.1.1/src/lib/components/FlowEditor.svelte +262 -0
- netrun_ui-0.1.1/src/lib/components/Modal.svelte +257 -0
- netrun_ui-0.1.1/src/lib/components/NetSettingsSection.svelte +242 -0
- netrun_ui-0.1.1/src/lib/components/NetrunNode.svelte +205 -0
- netrun_ui-0.1.1/src/lib/components/NodeExecutionSection.svelte +582 -0
- netrun_ui-0.1.1/src/lib/components/PoolsSection.svelte +448 -0
- netrun_ui-0.1.1/src/lib/components/ProjectSettings.svelte +535 -0
- netrun_ui-0.1.1/src/lib/components/SalvoConditionEditor.svelte +590 -0
- netrun_ui-0.1.1/src/lib/components/SalvoConditionsSection.svelte +303 -0
- netrun_ui-0.1.1/src/lib/components/Sidebar.svelte +1427 -0
- netrun_ui-0.1.1/src/lib/components/SubgraphNode.svelte +246 -0
- netrun_ui-0.1.1/src/lib/components/TabBar.svelte +188 -0
- netrun_ui-0.1.1/src/lib/components/TextInputModal.svelte +218 -0
- netrun_ui-0.1.1/src/lib/components/ToastContainer.svelte +126 -0
- netrun_ui-0.1.1/src/lib/components/Toolbar.svelte +404 -0
- netrun_ui-0.1.1/src/lib/index.ts +12 -0
- netrun_ui-0.1.1/src/lib/stores/actionsStore.ts +253 -0
- netrun_ui-0.1.1/src/lib/stores/clipboardStore.ts +59 -0
- netrun_ui-0.1.1/src/lib/stores/commandStore.ts +242 -0
- netrun_ui-0.1.1/src/lib/stores/factorySelectorStore.ts +51 -0
- netrun_ui-0.1.1/src/lib/stores/fileExplorerStore.ts +44 -0
- netrun_ui-0.1.1/src/lib/stores/flowStore.ts +1464 -0
- netrun_ui-0.1.1/src/lib/stores/keyboardStore.ts +165 -0
- netrun_ui-0.1.1/src/lib/stores/modalStore.ts +132 -0
- netrun_ui-0.1.1/src/lib/stores/recentFilesStore.ts +90 -0
- netrun_ui-0.1.1/src/lib/stores/tabsStore.ts +445 -0
- netrun_ui-0.1.1/src/lib/stores/toastStore.ts +44 -0
- netrun_ui-0.1.1/src/lib/stores/urlStore.ts +136 -0
- netrun_ui-0.1.1/src/lib/types/salvoConditions.ts +290 -0
- netrun_ui-0.1.1/src/lib/utils/salvoParser.ts +616 -0
- netrun_ui-0.1.1/src/lib/utils/salvoSerializer.ts +485 -0
- netrun_ui-0.1.1/src/routes/+layout.svelte +15 -0
- netrun_ui-0.1.1/src/routes/+layout.ts +5 -0
- netrun_ui-0.1.1/src/routes/+page.svelte +372 -0
- netrun_ui-0.1.1/src/routes/+page.ts +22 -0
- netrun_ui-0.1.1/static/robots.txt +3 -0
- netrun_ui-0.1.1/svelte.config.js +16 -0
- netrun_ui-0.1.1/testing/src/code.py +1 -0
- netrun_ui-0.1.1/tsconfig.json +20 -0
- netrun_ui-0.1.1/vite.config.ts +6 -0
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
node_modules
|
|
2
|
+
|
|
3
|
+
# Output
|
|
4
|
+
.output
|
|
5
|
+
.vercel
|
|
6
|
+
.netlify
|
|
7
|
+
.wrangler
|
|
8
|
+
/.svelte-kit
|
|
9
|
+
/build
|
|
10
|
+
|
|
11
|
+
# OS
|
|
12
|
+
.DS_Store
|
|
13
|
+
Thumbs.db
|
|
14
|
+
|
|
15
|
+
# Env
|
|
16
|
+
.env
|
|
17
|
+
.env.*
|
|
18
|
+
!.env.example
|
|
19
|
+
!.env.test
|
|
20
|
+
|
|
21
|
+
# Vite
|
|
22
|
+
vite.config.js.timestamp-*
|
|
23
|
+
vite.config.ts.timestamp-*
|
|
24
|
+
|
|
25
|
+
# Python
|
|
26
|
+
__pycache__/
|
|
27
|
+
*.py[cod]
|
|
28
|
+
*$py.class
|
|
29
|
+
*.so
|
|
30
|
+
.Python
|
|
31
|
+
dist/
|
|
32
|
+
*.egg-info/
|
|
33
|
+
.installed.cfg
|
|
34
|
+
*.egg
|
|
35
|
+
|
|
36
|
+
# Virtual environments
|
|
37
|
+
.venv/
|
|
38
|
+
venv/
|
|
39
|
+
ENV/
|
|
40
|
+
|
|
41
|
+
# IDE
|
|
42
|
+
.idea/
|
|
43
|
+
.vscode/
|
|
44
|
+
*.swp
|
|
45
|
+
*.swo
|
|
46
|
+
|
|
47
|
+
# Testing
|
|
48
|
+
.pytest_cache/
|
|
49
|
+
.coverage
|
|
50
|
+
htmlcov/
|
|
51
|
+
|
|
52
|
+
# mypy
|
|
53
|
+
.mypy_cache/
|
|
54
|
+
|
|
55
|
+
# Built frontend (generated during pip install)
|
|
56
|
+
netrun_ui_backend/static/
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
# netrun-ui
|
|
2
|
+
|
|
3
|
+
Visual editor for netrun flow configurations.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
pip install netrun-ui
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Usage
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
# Open native window (default)
|
|
15
|
+
netrun-ui
|
|
16
|
+
|
|
17
|
+
# Start server for browser access
|
|
18
|
+
netrun-ui --server
|
|
19
|
+
|
|
20
|
+
# Specify working directory
|
|
21
|
+
netrun-ui -C /path/to/project
|
|
22
|
+
|
|
23
|
+
# Custom port
|
|
24
|
+
netrun-ui --port 8080
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
### Development Mode
|
|
28
|
+
|
|
29
|
+
If you have the source code and Node.js installed:
|
|
30
|
+
|
|
31
|
+
```bash
|
|
32
|
+
# Development mode with hot reload
|
|
33
|
+
netrun-ui --dev
|
|
34
|
+
|
|
35
|
+
# Development server mode (for browser)
|
|
36
|
+
netrun-ui --dev --server
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
## Building from Source
|
|
40
|
+
|
|
41
|
+
1. Clone the repository
|
|
42
|
+
2. Install Node.js dependencies: `npm install`
|
|
43
|
+
3. Install the package: `pip install -e .` (this auto-builds the frontend)
|
|
44
|
+
|
|
45
|
+
## CLI Options
|
|
46
|
+
|
|
47
|
+
```
|
|
48
|
+
netrun-ui [OPTIONS]
|
|
49
|
+
|
|
50
|
+
Options:
|
|
51
|
+
-s, --server Run in server mode (browser) instead of native window
|
|
52
|
+
-d, --dev Development mode: use Vite dev server (requires Node.js)
|
|
53
|
+
-p, --port PORT Backend server port (default: 8000)
|
|
54
|
+
--frontend-port PORT Frontend dev server port, only used with --dev (default: 5173)
|
|
55
|
+
-C, --working-dir DIR Working directory for file explorer (default: current directory)
|
|
56
|
+
--width WIDTH Window width in app mode (default: 1400)
|
|
57
|
+
--height HEIGHT Window height in app mode (default: 900)
|
|
58
|
+
```
|
netrun_ui-0.1.1/PKG-INFO
ADDED
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: netrun-ui
|
|
3
|
+
Version: 0.1.1
|
|
4
|
+
Summary: Visual editor for netrun flow configurations
|
|
5
|
+
Requires-Python: >=3.11
|
|
6
|
+
Requires-Dist: fastapi>=0.109.0
|
|
7
|
+
Requires-Dist: netrun>=0.2.1
|
|
8
|
+
Requires-Dist: pydantic>=2.0.0
|
|
9
|
+
Requires-Dist: pywebview>=5.0.0
|
|
10
|
+
Requires-Dist: tomli-w>=1.0.0
|
|
11
|
+
Requires-Dist: tomli>=2.0.0
|
|
12
|
+
Requires-Dist: uvicorn[standard]>=0.27.0
|
|
13
|
+
Requires-Dist: websockets>=12.0
|
|
14
|
+
Provides-Extra: dev
|
|
15
|
+
Requires-Dist: httpx>=0.25.0; extra == 'dev'
|
|
16
|
+
Requires-Dist: pytest>=7.0.0; extra == 'dev'
|
|
17
|
+
Description-Content-Type: text/markdown
|
|
18
|
+
|
|
19
|
+
# netrun-ui
|
|
20
|
+
|
|
21
|
+
Visual editor for netrun flow configurations.
|
|
22
|
+
|
|
23
|
+
## Installation
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
pip install netrun-ui
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
## Usage
|
|
30
|
+
|
|
31
|
+
```bash
|
|
32
|
+
# Open native window (default)
|
|
33
|
+
netrun-ui
|
|
34
|
+
|
|
35
|
+
# Start server for browser access
|
|
36
|
+
netrun-ui --server
|
|
37
|
+
|
|
38
|
+
# Specify working directory
|
|
39
|
+
netrun-ui -C /path/to/project
|
|
40
|
+
|
|
41
|
+
# Custom port
|
|
42
|
+
netrun-ui --port 8080
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
### Development Mode
|
|
46
|
+
|
|
47
|
+
If you have the source code and Node.js installed:
|
|
48
|
+
|
|
49
|
+
```bash
|
|
50
|
+
# Development mode with hot reload
|
|
51
|
+
netrun-ui --dev
|
|
52
|
+
|
|
53
|
+
# Development server mode (for browser)
|
|
54
|
+
netrun-ui --dev --server
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
## Building from Source
|
|
58
|
+
|
|
59
|
+
1. Clone the repository
|
|
60
|
+
2. Install Node.js dependencies: `npm install`
|
|
61
|
+
3. Install the package: `pip install -e .` (this auto-builds the frontend)
|
|
62
|
+
|
|
63
|
+
## CLI Options
|
|
64
|
+
|
|
65
|
+
```
|
|
66
|
+
netrun-ui [OPTIONS]
|
|
67
|
+
|
|
68
|
+
Options:
|
|
69
|
+
-s, --server Run in server mode (browser) instead of native window
|
|
70
|
+
-d, --dev Development mode: use Vite dev server (requires Node.js)
|
|
71
|
+
-p, --port PORT Backend server port (default: 8000)
|
|
72
|
+
--frontend-port PORT Frontend dev server port, only used with --dev (default: 5173)
|
|
73
|
+
-C, --working-dir DIR Working directory for file explorer (default: current directory)
|
|
74
|
+
--width WIDTH Window width in app mode (default: 1400)
|
|
75
|
+
--height HEIGHT Window height in app mode (default: 900)
|
|
76
|
+
```
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
"""Custom build hook for hatchling to build the frontend before packaging."""
|
|
2
|
+
|
|
3
|
+
import shutil
|
|
4
|
+
import subprocess
|
|
5
|
+
import sys
|
|
6
|
+
from pathlib import Path
|
|
7
|
+
|
|
8
|
+
from hatchling.builders.hooks.plugin.interface import BuildHookInterface
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class FrontendBuildHook(BuildHookInterface):
|
|
12
|
+
"""Build the Svelte frontend before creating the Python package."""
|
|
13
|
+
|
|
14
|
+
PLUGIN_NAME = "frontend-build"
|
|
15
|
+
|
|
16
|
+
def initialize(self, version: str, build_data: dict) -> None:
|
|
17
|
+
"""Build the frontend if static files don't exist."""
|
|
18
|
+
root = Path(self.root)
|
|
19
|
+
static_dir = root / "netrun_ui_backend" / "static"
|
|
20
|
+
|
|
21
|
+
# Skip if static files already exist
|
|
22
|
+
if static_dir.exists() and (static_dir / "index.html").exists():
|
|
23
|
+
return
|
|
24
|
+
|
|
25
|
+
# Check if we have frontend source
|
|
26
|
+
if not (root / "package.json").exists():
|
|
27
|
+
# No source, no static - this will fail at runtime
|
|
28
|
+
# but we can't build without source
|
|
29
|
+
return
|
|
30
|
+
|
|
31
|
+
print("Building frontend...")
|
|
32
|
+
|
|
33
|
+
# Install npm dependencies if needed
|
|
34
|
+
if not (root / "node_modules").exists():
|
|
35
|
+
print("Installing npm dependencies...")
|
|
36
|
+
result = subprocess.run(
|
|
37
|
+
["npm", "install"],
|
|
38
|
+
cwd=str(root),
|
|
39
|
+
capture_output=True,
|
|
40
|
+
text=True,
|
|
41
|
+
)
|
|
42
|
+
if result.returncode != 0:
|
|
43
|
+
print(f"Warning: npm install failed: {result.stderr}", file=sys.stderr)
|
|
44
|
+
return
|
|
45
|
+
|
|
46
|
+
# Build the frontend
|
|
47
|
+
result = subprocess.run(
|
|
48
|
+
["npm", "run", "build"],
|
|
49
|
+
cwd=str(root),
|
|
50
|
+
capture_output=True,
|
|
51
|
+
text=True,
|
|
52
|
+
)
|
|
53
|
+
|
|
54
|
+
if result.returncode != 0:
|
|
55
|
+
print(f"Warning: Frontend build failed: {result.stderr}", file=sys.stderr)
|
|
56
|
+
print(result.stdout)
|
|
57
|
+
return
|
|
58
|
+
|
|
59
|
+
# Copy build to static directory
|
|
60
|
+
build_dir = root / "build"
|
|
61
|
+
if build_dir.exists():
|
|
62
|
+
if static_dir.exists():
|
|
63
|
+
shutil.rmtree(static_dir)
|
|
64
|
+
shutil.copytree(build_dir, static_dir)
|
|
65
|
+
print("Frontend built successfully.")
|
|
66
|
+
else:
|
|
67
|
+
print("Warning: Build directory not found after npm build", file=sys.stderr)
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"""netrun-ui backend API."""
|
|
@@ -0,0 +1,394 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""
|
|
3
|
+
netrun-ui CLI
|
|
4
|
+
|
|
5
|
+
Usage:
|
|
6
|
+
netrun-ui # Open native window (production)
|
|
7
|
+
netrun-ui --server # Start server mode (production)
|
|
8
|
+
netrun-ui --dev # Development mode with Vite
|
|
9
|
+
netrun-ui --port 8080 # Custom backend port
|
|
10
|
+
netrun-ui -C /path/to/project # Set working directory
|
|
11
|
+
"""
|
|
12
|
+
|
|
13
|
+
import argparse
|
|
14
|
+
import os
|
|
15
|
+
import signal
|
|
16
|
+
import subprocess
|
|
17
|
+
import sys
|
|
18
|
+
import threading
|
|
19
|
+
import time
|
|
20
|
+
from pathlib import Path
|
|
21
|
+
from typing import Optional
|
|
22
|
+
|
|
23
|
+
import uvicorn
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
def get_package_dir() -> Path:
|
|
27
|
+
"""Get the directory containing this package."""
|
|
28
|
+
return Path(__file__).parent.resolve()
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
def get_frontend_dir() -> Path:
|
|
32
|
+
"""Get the frontend directory (for development mode)."""
|
|
33
|
+
# The frontend is one level up from netrun_ui_backend/
|
|
34
|
+
return get_package_dir().parent
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
def has_static_files() -> bool:
|
|
38
|
+
"""Check if built static files exist."""
|
|
39
|
+
static_dir = get_package_dir() / "static"
|
|
40
|
+
return static_dir.exists() and (static_dir / "index.html").exists()
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
def has_frontend_source() -> bool:
|
|
44
|
+
"""Check if frontend source exists (for development)."""
|
|
45
|
+
frontend_dir = get_frontend_dir()
|
|
46
|
+
return (frontend_dir / "package.json").exists()
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
def start_backend_server(host: str = "127.0.0.1", port: int = 8000, log_level: str = "info") -> None:
|
|
50
|
+
"""Start the FastAPI backend server."""
|
|
51
|
+
uvicorn.run(
|
|
52
|
+
"netrun_ui_backend.main:app",
|
|
53
|
+
host=host,
|
|
54
|
+
port=port,
|
|
55
|
+
log_level=log_level,
|
|
56
|
+
)
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
def wait_for_server(url: str, timeout: float = 30.0) -> bool:
|
|
60
|
+
"""Wait for a server to become available."""
|
|
61
|
+
import urllib.request
|
|
62
|
+
import urllib.error
|
|
63
|
+
|
|
64
|
+
start_time = time.time()
|
|
65
|
+
while time.time() - start_time < timeout:
|
|
66
|
+
try:
|
|
67
|
+
urllib.request.urlopen(url, timeout=1)
|
|
68
|
+
return True
|
|
69
|
+
except (urllib.error.URLError, ConnectionRefusedError):
|
|
70
|
+
time.sleep(0.2)
|
|
71
|
+
return False
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
def start_frontend_dev_server(
|
|
75
|
+
frontend_dir: Path,
|
|
76
|
+
port: int = 5173,
|
|
77
|
+
initial_path: Optional[str] = None,
|
|
78
|
+
) -> subprocess.Popen:
|
|
79
|
+
"""Start the Vite frontend dev server (development mode only)."""
|
|
80
|
+
env = os.environ.copy()
|
|
81
|
+
if initial_path:
|
|
82
|
+
env["VITE_INITIAL_PATH"] = initial_path
|
|
83
|
+
|
|
84
|
+
# Pass port to Vite via -- separator
|
|
85
|
+
cmd = ["npm", "run", "dev", "--", "--port", str(port)]
|
|
86
|
+
|
|
87
|
+
try:
|
|
88
|
+
process = subprocess.Popen(
|
|
89
|
+
cmd,
|
|
90
|
+
cwd=str(frontend_dir),
|
|
91
|
+
env=env,
|
|
92
|
+
stdout=subprocess.PIPE,
|
|
93
|
+
stderr=subprocess.STDOUT,
|
|
94
|
+
)
|
|
95
|
+
return process
|
|
96
|
+
except FileNotFoundError:
|
|
97
|
+
print("Error: npm not found. Please install Node.js.", file=sys.stderr)
|
|
98
|
+
sys.exit(1)
|
|
99
|
+
|
|
100
|
+
|
|
101
|
+
def run_production_server(
|
|
102
|
+
port: int = 8000,
|
|
103
|
+
initial_path: Optional[str] = None,
|
|
104
|
+
) -> None:
|
|
105
|
+
"""Run in production server mode: backend serves static files."""
|
|
106
|
+
if not has_static_files():
|
|
107
|
+
print("Error: No built frontend found.", file=sys.stderr)
|
|
108
|
+
print("Either:", file=sys.stderr)
|
|
109
|
+
print(" 1. Run 'netrun-ui --dev' for development mode", file=sys.stderr)
|
|
110
|
+
print(" 2. Build the frontend first with the build script", file=sys.stderr)
|
|
111
|
+
sys.exit(1)
|
|
112
|
+
|
|
113
|
+
print("Starting netrun-ui server...")
|
|
114
|
+
print()
|
|
115
|
+
print(f" URL: http://127.0.0.1:{port}")
|
|
116
|
+
print(f" Working dir: {initial_path or os.getcwd()}")
|
|
117
|
+
print()
|
|
118
|
+
print("Press Ctrl+C to stop.")
|
|
119
|
+
|
|
120
|
+
# Set working directory for file explorer
|
|
121
|
+
if initial_path:
|
|
122
|
+
os.environ["NETRUN_UI_WORKING_DIR"] = initial_path
|
|
123
|
+
|
|
124
|
+
# Start backend (blocks)
|
|
125
|
+
start_backend_server(port=port, log_level="info")
|
|
126
|
+
|
|
127
|
+
|
|
128
|
+
def run_production_app(
|
|
129
|
+
port: int = 8000,
|
|
130
|
+
initial_path: Optional[str] = None,
|
|
131
|
+
width: int = 1400,
|
|
132
|
+
height: int = 900,
|
|
133
|
+
) -> None:
|
|
134
|
+
"""Run in production app mode: native window with built frontend."""
|
|
135
|
+
import webview
|
|
136
|
+
|
|
137
|
+
if not has_static_files():
|
|
138
|
+
print("Error: No built frontend found.", file=sys.stderr)
|
|
139
|
+
print("Either:", file=sys.stderr)
|
|
140
|
+
print(" 1. Run 'netrun-ui --dev' for development mode", file=sys.stderr)
|
|
141
|
+
print(" 2. Build the frontend first with the build script", file=sys.stderr)
|
|
142
|
+
sys.exit(1)
|
|
143
|
+
|
|
144
|
+
print("Starting netrun-ui...")
|
|
145
|
+
|
|
146
|
+
# Set working directory for file explorer
|
|
147
|
+
if initial_path:
|
|
148
|
+
os.environ["NETRUN_UI_WORKING_DIR"] = initial_path
|
|
149
|
+
|
|
150
|
+
# Start backend in background thread
|
|
151
|
+
backend_thread = threading.Thread(
|
|
152
|
+
target=start_backend_server,
|
|
153
|
+
kwargs={"port": port, "log_level": "warning"},
|
|
154
|
+
daemon=True,
|
|
155
|
+
)
|
|
156
|
+
backend_thread.start()
|
|
157
|
+
|
|
158
|
+
# Wait for backend
|
|
159
|
+
backend_url = f"http://127.0.0.1:{port}"
|
|
160
|
+
if not wait_for_server(f"{backend_url}/health", timeout=10):
|
|
161
|
+
print("Error: Backend failed to start", file=sys.stderr)
|
|
162
|
+
sys.exit(1)
|
|
163
|
+
|
|
164
|
+
# Open native window pointing to backend (which serves static files)
|
|
165
|
+
print("Opening window...")
|
|
166
|
+
window = webview.create_window(
|
|
167
|
+
"netrun-ui",
|
|
168
|
+
backend_url,
|
|
169
|
+
width=width,
|
|
170
|
+
height=height,
|
|
171
|
+
min_size=(800, 600),
|
|
172
|
+
)
|
|
173
|
+
|
|
174
|
+
webview.start()
|
|
175
|
+
print("Shutting down...")
|
|
176
|
+
|
|
177
|
+
|
|
178
|
+
def run_dev_server(
|
|
179
|
+
backend_port: int = 8000,
|
|
180
|
+
frontend_port: int = 5173,
|
|
181
|
+
initial_path: Optional[str] = None,
|
|
182
|
+
) -> None:
|
|
183
|
+
"""Run in development server mode: Vite + backend."""
|
|
184
|
+
if not has_frontend_source():
|
|
185
|
+
print("Error: Frontend source not found.", file=sys.stderr)
|
|
186
|
+
print("Development mode requires the frontend source code.", file=sys.stderr)
|
|
187
|
+
sys.exit(1)
|
|
188
|
+
|
|
189
|
+
frontend_dir = get_frontend_dir()
|
|
190
|
+
|
|
191
|
+
print("Starting netrun-ui in development mode...")
|
|
192
|
+
print()
|
|
193
|
+
|
|
194
|
+
# Start backend in background thread
|
|
195
|
+
print(f"Starting backend on http://127.0.0.1:{backend_port}...")
|
|
196
|
+
backend_thread = threading.Thread(
|
|
197
|
+
target=start_backend_server,
|
|
198
|
+
kwargs={"port": backend_port, "log_level": "info"},
|
|
199
|
+
daemon=True,
|
|
200
|
+
)
|
|
201
|
+
backend_thread.start()
|
|
202
|
+
|
|
203
|
+
# Wait for backend
|
|
204
|
+
if not wait_for_server(f"http://127.0.0.1:{backend_port}/health", timeout=10):
|
|
205
|
+
print("Warning: Backend may not be ready", file=sys.stderr)
|
|
206
|
+
|
|
207
|
+
# Start frontend
|
|
208
|
+
print(f"Starting frontend on http://localhost:{frontend_port}...")
|
|
209
|
+
frontend_process = start_frontend_dev_server(
|
|
210
|
+
frontend_dir,
|
|
211
|
+
port=frontend_port,
|
|
212
|
+
initial_path=initial_path or os.getcwd(),
|
|
213
|
+
)
|
|
214
|
+
|
|
215
|
+
print()
|
|
216
|
+
print("Development servers started!")
|
|
217
|
+
print(f" Backend: http://127.0.0.1:{backend_port}")
|
|
218
|
+
print(f" Frontend: http://localhost:{frontend_port}")
|
|
219
|
+
print()
|
|
220
|
+
print("Press Ctrl+C to stop.")
|
|
221
|
+
|
|
222
|
+
# Handle shutdown
|
|
223
|
+
def shutdown(signum, frame):
|
|
224
|
+
print("\nShutting down...")
|
|
225
|
+
frontend_process.terminate()
|
|
226
|
+
sys.exit(0)
|
|
227
|
+
|
|
228
|
+
signal.signal(signal.SIGINT, shutdown)
|
|
229
|
+
signal.signal(signal.SIGTERM, shutdown)
|
|
230
|
+
|
|
231
|
+
# Wait for frontend process
|
|
232
|
+
try:
|
|
233
|
+
frontend_process.wait()
|
|
234
|
+
except KeyboardInterrupt:
|
|
235
|
+
frontend_process.terminate()
|
|
236
|
+
|
|
237
|
+
|
|
238
|
+
def run_dev_app(
|
|
239
|
+
backend_port: int = 8000,
|
|
240
|
+
frontend_port: int = 5173,
|
|
241
|
+
initial_path: Optional[str] = None,
|
|
242
|
+
width: int = 1400,
|
|
243
|
+
height: int = 900,
|
|
244
|
+
) -> None:
|
|
245
|
+
"""Run in development app mode: native window with Vite."""
|
|
246
|
+
import webview
|
|
247
|
+
|
|
248
|
+
if not has_frontend_source():
|
|
249
|
+
print("Error: Frontend source not found.", file=sys.stderr)
|
|
250
|
+
print("Development mode requires the frontend source code.", file=sys.stderr)
|
|
251
|
+
sys.exit(1)
|
|
252
|
+
|
|
253
|
+
frontend_dir = get_frontend_dir()
|
|
254
|
+
|
|
255
|
+
print("Starting netrun-ui in development mode...")
|
|
256
|
+
|
|
257
|
+
# Start frontend dev server in background
|
|
258
|
+
print("Starting frontend server...")
|
|
259
|
+
frontend_process = start_frontend_dev_server(
|
|
260
|
+
frontend_dir,
|
|
261
|
+
port=frontend_port,
|
|
262
|
+
initial_path=initial_path or os.getcwd(),
|
|
263
|
+
)
|
|
264
|
+
|
|
265
|
+
# Wait for frontend to be ready
|
|
266
|
+
frontend_url = f"http://localhost:{frontend_port}"
|
|
267
|
+
if not wait_for_server(frontend_url, timeout=30):
|
|
268
|
+
print("Error: Frontend server failed to start", file=sys.stderr)
|
|
269
|
+
frontend_process.terminate()
|
|
270
|
+
sys.exit(1)
|
|
271
|
+
|
|
272
|
+
# Start backend in background thread
|
|
273
|
+
print("Starting backend server...")
|
|
274
|
+
backend_thread = threading.Thread(
|
|
275
|
+
target=start_backend_server,
|
|
276
|
+
kwargs={"port": backend_port, "log_level": "warning"},
|
|
277
|
+
daemon=True,
|
|
278
|
+
)
|
|
279
|
+
backend_thread.start()
|
|
280
|
+
|
|
281
|
+
# Wait for backend
|
|
282
|
+
if not wait_for_server(f"http://127.0.0.1:{backend_port}/health", timeout=10):
|
|
283
|
+
print("Warning: Backend may not be ready", file=sys.stderr)
|
|
284
|
+
|
|
285
|
+
# Open native window
|
|
286
|
+
print("Opening window...")
|
|
287
|
+
window = webview.create_window(
|
|
288
|
+
"netrun-ui (dev)",
|
|
289
|
+
frontend_url,
|
|
290
|
+
width=width,
|
|
291
|
+
height=height,
|
|
292
|
+
min_size=(800, 600),
|
|
293
|
+
)
|
|
294
|
+
|
|
295
|
+
# This blocks until window is closed
|
|
296
|
+
webview.start()
|
|
297
|
+
|
|
298
|
+
# Cleanup
|
|
299
|
+
print("Shutting down...")
|
|
300
|
+
frontend_process.terminate()
|
|
301
|
+
|
|
302
|
+
|
|
303
|
+
def main() -> None:
|
|
304
|
+
parser = argparse.ArgumentParser(
|
|
305
|
+
description="netrun-ui - Visual editor for netrun flow configurations",
|
|
306
|
+
formatter_class=argparse.RawDescriptionHelpFormatter,
|
|
307
|
+
epilog="""
|
|
308
|
+
Examples:
|
|
309
|
+
netrun-ui Open native window
|
|
310
|
+
netrun-ui --server Start server for browser access
|
|
311
|
+
netrun-ui --dev Development mode (requires Node.js)
|
|
312
|
+
netrun-ui --dev --server Development server mode
|
|
313
|
+
netrun-ui -C /path/to/project Set working directory
|
|
314
|
+
netrun-ui --port 8080 Use custom port
|
|
315
|
+
""",
|
|
316
|
+
)
|
|
317
|
+
|
|
318
|
+
parser.add_argument(
|
|
319
|
+
"--server", "-s",
|
|
320
|
+
action="store_true",
|
|
321
|
+
help="Run in server mode (browser) instead of native window",
|
|
322
|
+
)
|
|
323
|
+
parser.add_argument(
|
|
324
|
+
"--dev", "-d",
|
|
325
|
+
action="store_true",
|
|
326
|
+
help="Development mode: use Vite dev server (requires Node.js)",
|
|
327
|
+
)
|
|
328
|
+
parser.add_argument(
|
|
329
|
+
"--port", "-p",
|
|
330
|
+
type=int,
|
|
331
|
+
default=8000,
|
|
332
|
+
help="Backend server port (default: 8000)",
|
|
333
|
+
)
|
|
334
|
+
parser.add_argument(
|
|
335
|
+
"--frontend-port",
|
|
336
|
+
type=int,
|
|
337
|
+
default=5173,
|
|
338
|
+
help="Frontend dev server port, only used with --dev (default: 5173)",
|
|
339
|
+
)
|
|
340
|
+
parser.add_argument(
|
|
341
|
+
"--working-dir", "-C",
|
|
342
|
+
help="Working directory for file explorer (default: current directory)",
|
|
343
|
+
)
|
|
344
|
+
parser.add_argument(
|
|
345
|
+
"--width",
|
|
346
|
+
type=int,
|
|
347
|
+
default=1400,
|
|
348
|
+
help="Window width in app mode (default: 1400)",
|
|
349
|
+
)
|
|
350
|
+
parser.add_argument(
|
|
351
|
+
"--height",
|
|
352
|
+
type=int,
|
|
353
|
+
default=900,
|
|
354
|
+
help="Window height in app mode (default: 900)",
|
|
355
|
+
)
|
|
356
|
+
|
|
357
|
+
args = parser.parse_args()
|
|
358
|
+
|
|
359
|
+
initial_path = args.working_dir or os.getcwd()
|
|
360
|
+
|
|
361
|
+
if args.dev:
|
|
362
|
+
# Development mode
|
|
363
|
+
if args.server:
|
|
364
|
+
run_dev_server(
|
|
365
|
+
backend_port=args.port,
|
|
366
|
+
frontend_port=args.frontend_port,
|
|
367
|
+
initial_path=initial_path,
|
|
368
|
+
)
|
|
369
|
+
else:
|
|
370
|
+
run_dev_app(
|
|
371
|
+
backend_port=args.port,
|
|
372
|
+
frontend_port=args.frontend_port,
|
|
373
|
+
initial_path=initial_path,
|
|
374
|
+
width=args.width,
|
|
375
|
+
height=args.height,
|
|
376
|
+
)
|
|
377
|
+
else:
|
|
378
|
+
# Production mode
|
|
379
|
+
if args.server:
|
|
380
|
+
run_production_server(
|
|
381
|
+
port=args.port,
|
|
382
|
+
initial_path=initial_path,
|
|
383
|
+
)
|
|
384
|
+
else:
|
|
385
|
+
run_production_app(
|
|
386
|
+
port=args.port,
|
|
387
|
+
initial_path=initial_path,
|
|
388
|
+
width=args.width,
|
|
389
|
+
height=args.height,
|
|
390
|
+
)
|
|
391
|
+
|
|
392
|
+
|
|
393
|
+
if __name__ == "__main__":
|
|
394
|
+
main()
|