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.
Files changed (67) hide show
  1. netrun_ui-0.1.1/.gitignore +56 -0
  2. netrun_ui-0.1.1/BACKEND_README.md +58 -0
  3. netrun_ui-0.1.1/PKG-INFO +76 -0
  4. netrun_ui-0.1.1/hatch_build.py +67 -0
  5. netrun_ui-0.1.1/netrun_ui_backend/__init__.py +1 -0
  6. netrun_ui-0.1.1/netrun_ui_backend/cli.py +394 -0
  7. netrun_ui-0.1.1/netrun_ui_backend/converter.py +370 -0
  8. netrun_ui-0.1.1/netrun_ui_backend/main.py +104 -0
  9. netrun_ui-0.1.1/netrun_ui_backend/routes/__init__.py +1 -0
  10. netrun_ui-0.1.1/netrun_ui_backend/routes/actions.py +279 -0
  11. netrun_ui-0.1.1/netrun_ui_backend/routes/factories.py +380 -0
  12. netrun_ui-0.1.1/netrun_ui_backend/routes/files.py +677 -0
  13. netrun_ui-0.1.1/package-lock.json +2022 -0
  14. netrun_ui-0.1.1/package.json +26 -0
  15. netrun_ui-0.1.1/pyproject.toml +57 -0
  16. netrun_ui-0.1.1/src/app.css +88 -0
  17. netrun_ui-0.1.1/src/app.d.ts +13 -0
  18. netrun_ui-0.1.1/src/app.html +11 -0
  19. netrun_ui-0.1.1/src/lib/api.ts +415 -0
  20. netrun_ui-0.1.1/src/lib/assets/favicon.svg +1 -0
  21. netrun_ui-0.1.1/src/lib/commands.ts +577 -0
  22. netrun_ui-0.1.1/src/lib/components/ActionEditor.svelte +327 -0
  23. netrun_ui-0.1.1/src/lib/components/ActionsPanel.svelte +368 -0
  24. netrun_ui-0.1.1/src/lib/components/Breadcrumb.svelte +75 -0
  25. netrun_ui-0.1.1/src/lib/components/CommandPalette.svelte +446 -0
  26. netrun_ui-0.1.1/src/lib/components/FactorySelectorModal.svelte +504 -0
  27. netrun_ui-0.1.1/src/lib/components/FileExplorer.svelte +359 -0
  28. netrun_ui-0.1.1/src/lib/components/FlowEditor.svelte +262 -0
  29. netrun_ui-0.1.1/src/lib/components/Modal.svelte +257 -0
  30. netrun_ui-0.1.1/src/lib/components/NetSettingsSection.svelte +242 -0
  31. netrun_ui-0.1.1/src/lib/components/NetrunNode.svelte +205 -0
  32. netrun_ui-0.1.1/src/lib/components/NodeExecutionSection.svelte +582 -0
  33. netrun_ui-0.1.1/src/lib/components/PoolsSection.svelte +448 -0
  34. netrun_ui-0.1.1/src/lib/components/ProjectSettings.svelte +535 -0
  35. netrun_ui-0.1.1/src/lib/components/SalvoConditionEditor.svelte +590 -0
  36. netrun_ui-0.1.1/src/lib/components/SalvoConditionsSection.svelte +303 -0
  37. netrun_ui-0.1.1/src/lib/components/Sidebar.svelte +1427 -0
  38. netrun_ui-0.1.1/src/lib/components/SubgraphNode.svelte +246 -0
  39. netrun_ui-0.1.1/src/lib/components/TabBar.svelte +188 -0
  40. netrun_ui-0.1.1/src/lib/components/TextInputModal.svelte +218 -0
  41. netrun_ui-0.1.1/src/lib/components/ToastContainer.svelte +126 -0
  42. netrun_ui-0.1.1/src/lib/components/Toolbar.svelte +404 -0
  43. netrun_ui-0.1.1/src/lib/index.ts +12 -0
  44. netrun_ui-0.1.1/src/lib/stores/actionsStore.ts +253 -0
  45. netrun_ui-0.1.1/src/lib/stores/clipboardStore.ts +59 -0
  46. netrun_ui-0.1.1/src/lib/stores/commandStore.ts +242 -0
  47. netrun_ui-0.1.1/src/lib/stores/factorySelectorStore.ts +51 -0
  48. netrun_ui-0.1.1/src/lib/stores/fileExplorerStore.ts +44 -0
  49. netrun_ui-0.1.1/src/lib/stores/flowStore.ts +1464 -0
  50. netrun_ui-0.1.1/src/lib/stores/keyboardStore.ts +165 -0
  51. netrun_ui-0.1.1/src/lib/stores/modalStore.ts +132 -0
  52. netrun_ui-0.1.1/src/lib/stores/recentFilesStore.ts +90 -0
  53. netrun_ui-0.1.1/src/lib/stores/tabsStore.ts +445 -0
  54. netrun_ui-0.1.1/src/lib/stores/toastStore.ts +44 -0
  55. netrun_ui-0.1.1/src/lib/stores/urlStore.ts +136 -0
  56. netrun_ui-0.1.1/src/lib/types/salvoConditions.ts +290 -0
  57. netrun_ui-0.1.1/src/lib/utils/salvoParser.ts +616 -0
  58. netrun_ui-0.1.1/src/lib/utils/salvoSerializer.ts +485 -0
  59. netrun_ui-0.1.1/src/routes/+layout.svelte +15 -0
  60. netrun_ui-0.1.1/src/routes/+layout.ts +5 -0
  61. netrun_ui-0.1.1/src/routes/+page.svelte +372 -0
  62. netrun_ui-0.1.1/src/routes/+page.ts +22 -0
  63. netrun_ui-0.1.1/static/robots.txt +3 -0
  64. netrun_ui-0.1.1/svelte.config.js +16 -0
  65. netrun_ui-0.1.1/testing/src/code.py +1 -0
  66. netrun_ui-0.1.1/tsconfig.json +20 -0
  67. 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
+ ```
@@ -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()