flock-core 0.4.0b34__py3-none-any.whl → 0.4.0b36__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.
Potentially problematic release.
This version of flock-core might be problematic. Click here for more details.
- flock/__init__.py +53 -8
- flock/cli/loaded_flock_cli.py +38 -18
- flock/core/api/main.py +138 -39
- flock/core/flock.py +48 -3
- flock/themes/alabaster.toml +43 -43
- flock/themes/guezwhoz.toml +43 -43
- flock/themes/wildcherry.toml +43 -43
- flock/themes/wombat.toml +43 -43
- flock/themes/zenburn.toml +43 -43
- flock/webapp/__init__.py +1 -0
- flock/webapp/app/__init__.py +0 -0
- flock/webapp/app/api/__init__.py +0 -0
- flock/webapp/app/api/agent_management.py +270 -0
- flock/webapp/app/api/execution.py +173 -0
- flock/webapp/app/api/flock_management.py +102 -0
- flock/webapp/app/api/registry_viewer.py +30 -0
- flock/webapp/app/config.py +87 -0
- flock/webapp/app/main.py +1074 -0
- flock/webapp/app/models_ui.py +7 -0
- flock/webapp/app/services/__init__.py +0 -0
- flock/webapp/app/services/flock_service.py +291 -0
- flock/webapp/app/templates/theme_mapper.html +326 -0
- flock/webapp/app/theme_mapper.py +812 -0
- flock/webapp/app/utils.py +85 -0
- flock/webapp/run.py +132 -0
- flock/webapp/static/css/custom.css +612 -0
- flock/webapp/templates/base.html +105 -0
- flock/webapp/templates/flock_editor.html +17 -0
- flock/webapp/templates/index.html +12 -0
- flock/webapp/templates/partials/_agent_detail_form.html +98 -0
- flock/webapp/templates/partials/_agent_list.html +19 -0
- flock/webapp/templates/partials/_agent_manager_view.html +53 -0
- flock/webapp/templates/partials/_agent_manager_view_old.html +19 -0
- flock/webapp/templates/partials/_agent_tools_checklist.html +14 -0
- flock/webapp/templates/partials/_create_flock_form.html +52 -0
- flock/webapp/templates/partials/_dashboard_flock_detail.html +18 -0
- flock/webapp/templates/partials/_dashboard_flock_file_list.html +17 -0
- flock/webapp/templates/partials/_dashboard_flock_properties_preview.html +29 -0
- flock/webapp/templates/partials/_dashboard_upload_flock_form.html +17 -0
- flock/webapp/templates/partials/_dynamic_input_form_content.html +22 -0
- flock/webapp/templates/partials/_env_vars_table.html +25 -0
- flock/webapp/templates/partials/_execution_form.html +48 -0
- flock/webapp/templates/partials/_execution_view_container.html +20 -0
- flock/webapp/templates/partials/_flock_file_list.html +24 -0
- flock/webapp/templates/partials/_flock_properties_form.html +52 -0
- flock/webapp/templates/partials/_flock_upload_form.html +17 -0
- flock/webapp/templates/partials/_header_flock_status.html +5 -0
- flock/webapp/templates/partials/_load_manager_view.html +50 -0
- flock/webapp/templates/partials/_registry_table.html +25 -0
- flock/webapp/templates/partials/_registry_viewer_content.html +47 -0
- flock/webapp/templates/partials/_results_display.html +35 -0
- flock/webapp/templates/partials/_settings_env_content.html +10 -0
- flock/webapp/templates/partials/_settings_theme_content.html +15 -0
- flock/webapp/templates/partials/_settings_view.html +36 -0
- flock/webapp/templates/partials/_sidebar.html +70 -0
- flock/webapp/templates/partials/_structured_data_view.html +40 -0
- flock/webapp/templates/partials/_theme_preview.html +23 -0
- flock/webapp/templates/registry_viewer.html +84 -0
- {flock_core-0.4.0b34.dist-info → flock_core-0.4.0b36.dist-info}/METADATA +1 -1
- {flock_core-0.4.0b34.dist-info → flock_core-0.4.0b36.dist-info}/RECORD +63 -14
- {flock_core-0.4.0b34.dist-info → flock_core-0.4.0b36.dist-info}/WHEEL +0 -0
- {flock_core-0.4.0b34.dist-info → flock_core-0.4.0b36.dist-info}/entry_points.txt +0 -0
- {flock_core-0.4.0b34.dist-info → flock_core-0.4.0b36.dist-info}/licenses/LICENSE +0 -0
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import inspect
|
|
2
|
+
import json
|
|
3
|
+
from typing import Any
|
|
4
|
+
|
|
5
|
+
def is_pydantic_model(obj: Any) -> bool:
|
|
6
|
+
"""
|
|
7
|
+
Check if an object is a Pydantic model instance.
|
|
8
|
+
More robust detection for both v1 and v2 Pydantic models.
|
|
9
|
+
"""
|
|
10
|
+
# Check for Pydantic v2 model
|
|
11
|
+
if hasattr(obj, "__class__") and hasattr(obj.__class__, "model_dump"):
|
|
12
|
+
return True
|
|
13
|
+
|
|
14
|
+
# Check for Pydantic v1 model
|
|
15
|
+
if hasattr(obj, "__class__") and hasattr(obj.__class__, "schema") and hasattr(obj, "dict"):
|
|
16
|
+
return True
|
|
17
|
+
|
|
18
|
+
# Check if it has a __pydantic_core__ attribute (v2 models)
|
|
19
|
+
if hasattr(obj, "__pydantic_core__"):
|
|
20
|
+
return True
|
|
21
|
+
|
|
22
|
+
# Final check: class name check and module check
|
|
23
|
+
if hasattr(obj, "__class__"):
|
|
24
|
+
cls = obj.__class__
|
|
25
|
+
cls_name = cls.__name__
|
|
26
|
+
module_name = getattr(cls, "__module__", "")
|
|
27
|
+
if "pydantic" in module_name.lower() or "basemodel" in cls_name.lower():
|
|
28
|
+
return True
|
|
29
|
+
|
|
30
|
+
return False
|
|
31
|
+
|
|
32
|
+
def is_json_serializable(obj: Any) -> bool:
|
|
33
|
+
"""Check if an object can be serialized to JSON."""
|
|
34
|
+
try:
|
|
35
|
+
json.dumps(obj)
|
|
36
|
+
return True
|
|
37
|
+
except (TypeError, ValueError):
|
|
38
|
+
return False
|
|
39
|
+
|
|
40
|
+
def pydantic_to_dict(obj: Any) -> Any:
|
|
41
|
+
"""
|
|
42
|
+
Recursively convert Pydantic models to dictionaries.
|
|
43
|
+
Works with nested models, lists, and dictionaries containing models.
|
|
44
|
+
Falls back to string representation if object can't be serialized.
|
|
45
|
+
"""
|
|
46
|
+
if obj is None:
|
|
47
|
+
return None
|
|
48
|
+
|
|
49
|
+
if is_pydantic_model(obj):
|
|
50
|
+
# Handle Pydantic v2 models
|
|
51
|
+
if hasattr(obj, "model_dump"):
|
|
52
|
+
return obj.model_dump()
|
|
53
|
+
# Handle Pydantic v1 models
|
|
54
|
+
elif hasattr(obj, "dict"):
|
|
55
|
+
return obj.dict()
|
|
56
|
+
# Last resort - try __dict__ if it exists
|
|
57
|
+
elif hasattr(obj, "__dict__"):
|
|
58
|
+
return {k: pydantic_to_dict(v) for k, v in obj.__dict__.items()
|
|
59
|
+
if not k.startswith("_")}
|
|
60
|
+
|
|
61
|
+
elif isinstance(obj, dict):
|
|
62
|
+
# Handle dictionaries that might contain Pydantic models
|
|
63
|
+
return {k: pydantic_to_dict(v) for k, v in obj.items()}
|
|
64
|
+
|
|
65
|
+
elif isinstance(obj, list):
|
|
66
|
+
# Handle lists that might contain Pydantic models
|
|
67
|
+
return [pydantic_to_dict(item) for item in obj]
|
|
68
|
+
|
|
69
|
+
elif isinstance(obj, tuple) and hasattr(obj, '_fields'):
|
|
70
|
+
# Handle namedtuples
|
|
71
|
+
return dict(zip(obj._fields, (pydantic_to_dict(item) for item in obj)))
|
|
72
|
+
|
|
73
|
+
elif isinstance(obj, (list, tuple)):
|
|
74
|
+
# Handle regular lists and tuples
|
|
75
|
+
return [pydantic_to_dict(item) for item in obj]
|
|
76
|
+
|
|
77
|
+
# Final check - if object is not JSON serializable, convert to string
|
|
78
|
+
if not is_json_serializable(obj):
|
|
79
|
+
try:
|
|
80
|
+
return str(obj)
|
|
81
|
+
except Exception:
|
|
82
|
+
return f"<Unserializable object of type {type(obj).__name__}>"
|
|
83
|
+
|
|
84
|
+
# Return other types unchanged - these should be JSON serializable by default
|
|
85
|
+
return obj
|
flock/webapp/run.py
ADDED
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
import os # For environment variable
|
|
2
|
+
import sys
|
|
3
|
+
from pathlib import Path
|
|
4
|
+
from typing import TYPE_CHECKING
|
|
5
|
+
|
|
6
|
+
import uvicorn
|
|
7
|
+
|
|
8
|
+
if TYPE_CHECKING:
|
|
9
|
+
from flock.core import Flock
|
|
10
|
+
|
|
11
|
+
# --- Integrated Server Function ---
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def start_integrated_server(
|
|
15
|
+
flock_instance: "Flock",
|
|
16
|
+
host: str,
|
|
17
|
+
port: int,
|
|
18
|
+
server_name: str, # Currently unused as UI sets its own title
|
|
19
|
+
theme_name: str | None = None,
|
|
20
|
+
):
|
|
21
|
+
"""Starts the webapp, preloads flock & theme, includes API routes (TODO)."""
|
|
22
|
+
print(
|
|
23
|
+
f"Starting integrated server for Flock '{flock_instance.name}' on {host}:{port}"
|
|
24
|
+
)
|
|
25
|
+
try:
|
|
26
|
+
# Ensure src is in path (important if called from core)
|
|
27
|
+
src_dir = Path(__file__).resolve().parent.parent
|
|
28
|
+
if str(src_dir) not in sys.path:
|
|
29
|
+
sys.path.insert(0, str(src_dir))
|
|
30
|
+
|
|
31
|
+
# Import necessary webapp components *after* path setup
|
|
32
|
+
from flock.core.api.run_store import (
|
|
33
|
+
RunStore, # Needed for API routes later
|
|
34
|
+
)
|
|
35
|
+
from flock.webapp.app.config import (
|
|
36
|
+
get_current_theme_name,
|
|
37
|
+
set_current_theme_name,
|
|
38
|
+
)
|
|
39
|
+
from flock.webapp.app.main import app as webapp_fastapi_app
|
|
40
|
+
from flock.webapp.app.services.flock_service import (
|
|
41
|
+
set_current_flock_instance_programmatically,
|
|
42
|
+
)
|
|
43
|
+
# from flock.core.api.endpoints import create_api_router # Need to adapt this later
|
|
44
|
+
|
|
45
|
+
# 1. Set Theme (use provided or default)
|
|
46
|
+
set_current_theme_name(
|
|
47
|
+
theme_name
|
|
48
|
+
) # Uses default from config if theme_name is None
|
|
49
|
+
print(f"Integrated server using theme: {get_current_theme_name()}")
|
|
50
|
+
|
|
51
|
+
# 2. Set Flock Instance
|
|
52
|
+
set_current_flock_instance_programmatically(
|
|
53
|
+
flock_instance,
|
|
54
|
+
f"{flock_instance.name.replace(' ', '_').lower()}_integrated.flock",
|
|
55
|
+
)
|
|
56
|
+
print(f"Flock '{flock_instance.name}' preloaded.")
|
|
57
|
+
|
|
58
|
+
# 3. TODO: Adapt and Include API Routes
|
|
59
|
+
# run_store = RunStore()
|
|
60
|
+
# api_router = create_api_router(flock_instance, run_store) # Assuming refactored signature
|
|
61
|
+
# webapp_fastapi_app.include_router(api_router, prefix="/api")
|
|
62
|
+
# print("API routes included.")
|
|
63
|
+
|
|
64
|
+
# 4. Run Uvicorn - STILL PASSING INSTANCE here because we need to modify it (add routes)
|
|
65
|
+
# and set state BEFORE running. Reload won't work well here.
|
|
66
|
+
uvicorn.run(
|
|
67
|
+
webapp_fastapi_app, host=host, port=port, reload=False
|
|
68
|
+
) # Ensure reload=False
|
|
69
|
+
|
|
70
|
+
except ImportError as e:
|
|
71
|
+
print(
|
|
72
|
+
f"Error importing components for integrated server: {e}",
|
|
73
|
+
file=sys.stderr,
|
|
74
|
+
)
|
|
75
|
+
print(
|
|
76
|
+
"Ensure all dependencies are installed and paths are correct.",
|
|
77
|
+
file=sys.stderr,
|
|
78
|
+
)
|
|
79
|
+
sys.exit(1)
|
|
80
|
+
except Exception as e:
|
|
81
|
+
print(f"Error starting integrated server: {e}", file=sys.stderr)
|
|
82
|
+
sys.exit(1)
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
# --- Standalone Webapp Runner (for `flock --web`) ---
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
def main():
|
|
89
|
+
"""Run the Flock web application standalone."""
|
|
90
|
+
# Theme is now set via environment variable read by config.py on import
|
|
91
|
+
# No need to explicitly set it here anymore.
|
|
92
|
+
print(f"Starting standalone webapp...")
|
|
93
|
+
# Ensure src is in path
|
|
94
|
+
src_dir = Path(__file__).resolve().parent.parent
|
|
95
|
+
if str(src_dir) not in sys.path:
|
|
96
|
+
sys.path.insert(0, str(src_dir))
|
|
97
|
+
|
|
98
|
+
try:
|
|
99
|
+
# Determine host, port, and reload settings
|
|
100
|
+
host = os.environ.get("FLOCK_WEB_HOST", "127.0.0.1")
|
|
101
|
+
port = int(os.environ.get("FLOCK_WEB_PORT", "8344"))
|
|
102
|
+
reload = os.environ.get("FLOCK_WEB_RELOAD", "true").lower() == "true"
|
|
103
|
+
# Use import string for app path
|
|
104
|
+
app_import_string = "flock.webapp.app.main:app"
|
|
105
|
+
|
|
106
|
+
# No need to import app instance here anymore for standalone mode
|
|
107
|
+
# from flock.webapp.app.main import app as webapp_fastapi_app
|
|
108
|
+
# from flock.webapp.app.config import get_current_theme_name
|
|
109
|
+
# print(f"Standalone webapp using theme: {get_current_theme_name()}") # Config now logs this on load
|
|
110
|
+
|
|
111
|
+
uvicorn.run(
|
|
112
|
+
app_import_string, # Use import string for reload capability
|
|
113
|
+
host=host,
|
|
114
|
+
port=port,
|
|
115
|
+
reload=reload,
|
|
116
|
+
)
|
|
117
|
+
except ImportError as e:
|
|
118
|
+
# Catch potential import error during uvicorn startup if path is wrong
|
|
119
|
+
print(f"Error loading webapp modules via Uvicorn: {e}", file=sys.stderr)
|
|
120
|
+
print(
|
|
121
|
+
"Make sure all required packages are installed and src path is correct.",
|
|
122
|
+
file=sys.stderr,
|
|
123
|
+
)
|
|
124
|
+
sys.exit(1)
|
|
125
|
+
except Exception as e:
|
|
126
|
+
print(f"Error starting standalone webapp: {e}", file=sys.stderr)
|
|
127
|
+
sys.exit(1)
|
|
128
|
+
|
|
129
|
+
|
|
130
|
+
# Note: The `if __name__ == "__main__":` block is removed as this module
|
|
131
|
+
# is now primarily meant to be called via `main()` or `start_integrated_server()`
|
|
132
|
+
# The CLI entry point will call `main()` after potentially calling `set_initial_theme()`.
|