flock-core 0.4.0b48__py3-none-any.whl → 0.4.0b49__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 +45 -3
- flock/modules/mem0/mem0_module.py +63 -0
- flock/modules/mem0graph/__init__.py +1 -0
- flock/modules/mem0graph/mem0_graph_module.py +63 -0
- flock/webapp/app/api/execution.py +130 -30
- flock/webapp/app/chat.py +303 -16
- flock/webapp/app/config.py +14 -0
- flock/webapp/app/dependencies.py +22 -0
- flock/webapp/app/main.py +400 -2
- flock/webapp/app/services/flock_service.py +38 -13
- flock/webapp/app/services/sharing_models.py +43 -0
- flock/webapp/app/services/sharing_store.py +156 -0
- flock/webapp/static/css/chat.css +57 -0
- flock/webapp/templates/chat.html +29 -4
- flock/webapp/templates/partials/_chat_messages.html +1 -1
- flock/webapp/templates/partials/_chat_settings_form.html +22 -0
- flock/webapp/templates/partials/_execution_form.html +28 -1
- flock/webapp/templates/partials/_share_chat_link_snippet.html +11 -0
- flock/webapp/templates/partials/_share_link_snippet.html +35 -0
- flock/webapp/templates/shared_run_page.html +116 -0
- {flock_core-0.4.0b48.dist-info → flock_core-0.4.0b49.dist-info}/METADATA +4 -2
- {flock_core-0.4.0b48.dist-info → flock_core-0.4.0b49.dist-info}/RECORD +26 -19
- flock/modules/zep/zep_module.py +0 -187
- /flock/modules/{zep → mem0}/__init__.py +0 -0
- {flock_core-0.4.0b48.dist-info → flock_core-0.4.0b49.dist-info}/WHEEL +0 -0
- {flock_core-0.4.0b48.dist-info → flock_core-0.4.0b49.dist-info}/entry_points.txt +0 -0
- {flock_core-0.4.0b48.dist-info → flock_core-0.4.0b49.dist-info}/licenses/LICENSE +0 -0
flock/__init__.py
CHANGED
|
@@ -16,6 +16,11 @@ def main():
|
|
|
16
16
|
action="store_true",
|
|
17
17
|
help="Start the web interface instead of the CLI",
|
|
18
18
|
)
|
|
19
|
+
parser.add_argument(
|
|
20
|
+
"--chat",
|
|
21
|
+
action="store_true",
|
|
22
|
+
help="Start a chat interface. If --web is also used, enables chat within the web app; otherwise, starts standalone chat.",
|
|
23
|
+
)
|
|
19
24
|
parser.add_argument(
|
|
20
25
|
"--theme",
|
|
21
26
|
type=str,
|
|
@@ -30,7 +35,7 @@ def main():
|
|
|
30
35
|
# Set environment variable for theme if provided
|
|
31
36
|
if args.theme:
|
|
32
37
|
print(
|
|
33
|
-
f"Setting FLOCK_WEB_THEME environment variable to: {args.theme}"
|
|
38
|
+
f"INFO: Setting FLOCK_WEB_THEME environment variable to: {args.theme}"
|
|
34
39
|
)
|
|
35
40
|
os.environ["FLOCK_WEB_THEME"] = args.theme
|
|
36
41
|
else:
|
|
@@ -38,10 +43,20 @@ def main():
|
|
|
38
43
|
if "FLOCK_WEB_THEME" in os.environ:
|
|
39
44
|
del os.environ["FLOCK_WEB_THEME"]
|
|
40
45
|
|
|
46
|
+
if args.chat: # --web --chat
|
|
47
|
+
print("INFO: Starting web application with chat feature enabled.")
|
|
48
|
+
os.environ["FLOCK_CHAT_ENABLED"] = "true"
|
|
49
|
+
else: # Just --web
|
|
50
|
+
print("INFO: Starting web application.")
|
|
51
|
+
if "FLOCK_CHAT_ENABLED" in os.environ:
|
|
52
|
+
del os.environ["FLOCK_CHAT_ENABLED"]
|
|
53
|
+
|
|
54
|
+
# Ensure standalone chat mode is not active
|
|
55
|
+
if "FLOCK_START_MODE" in os.environ:
|
|
56
|
+
del os.environ["FLOCK_START_MODE"]
|
|
57
|
+
|
|
41
58
|
# Import and run the standalone webapp main function
|
|
42
|
-
# It will now read the theme from the environment variable
|
|
43
59
|
from flock.webapp.run import main as run_webapp_main
|
|
44
|
-
|
|
45
60
|
run_webapp_main()
|
|
46
61
|
|
|
47
62
|
except ImportError:
|
|
@@ -55,6 +70,33 @@ def main():
|
|
|
55
70
|
sys.exit(1)
|
|
56
71
|
return
|
|
57
72
|
|
|
73
|
+
elif args.chat: # Standalone chat mode (args.web is false)
|
|
74
|
+
try:
|
|
75
|
+
print("INFO: Starting standalone chat application.")
|
|
76
|
+
os.environ["FLOCK_START_MODE"] = "chat"
|
|
77
|
+
|
|
78
|
+
# Clear web-specific env vars that might conflict or not apply
|
|
79
|
+
if "FLOCK_WEB_THEME" in os.environ:
|
|
80
|
+
del os.environ["FLOCK_WEB_THEME"]
|
|
81
|
+
if "FLOCK_CHAT_ENABLED" in os.environ:
|
|
82
|
+
del os.environ["FLOCK_CHAT_ENABLED"]
|
|
83
|
+
|
|
84
|
+
# Handle --theme if passed with --chat only
|
|
85
|
+
if args.theme:
|
|
86
|
+
print(f"INFO: Standalone chat mode started with --theme '{args.theme}'. FLOCK_WEB_THEME will be set.")
|
|
87
|
+
os.environ["FLOCK_WEB_THEME"] = args.theme
|
|
88
|
+
|
|
89
|
+
from flock.webapp.run import main as run_webapp_main
|
|
90
|
+
run_webapp_main() # The webapp main needs to interpret FLOCK_START_MODE="chat"
|
|
91
|
+
|
|
92
|
+
except ImportError:
|
|
93
|
+
print("Error: Could not import webapp components for chat. Ensure web dependencies are installed.", file=sys.stderr)
|
|
94
|
+
sys.exit(1)
|
|
95
|
+
except Exception as e:
|
|
96
|
+
print(f"Error starting standalone chat application: {e}", file=sys.stderr)
|
|
97
|
+
sys.exit(1)
|
|
98
|
+
return
|
|
99
|
+
|
|
58
100
|
# Otherwise, run the CLI interface
|
|
59
101
|
import questionary
|
|
60
102
|
from rich.console import Console
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
from typing import Any
|
|
2
|
+
|
|
3
|
+
from pydantic import Field
|
|
4
|
+
|
|
5
|
+
from flock.core.context.context import FlockContext
|
|
6
|
+
from flock.core.flock_agent import FlockAgent
|
|
7
|
+
from flock.core.flock_module import FlockModule, FlockModuleConfig
|
|
8
|
+
from flock.core.flock_registry import flock_component
|
|
9
|
+
from flock.core.logging.logging import get_logger
|
|
10
|
+
|
|
11
|
+
logger = get_logger("module.mem0")
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class Mem0ModuleConfig(FlockModuleConfig):
|
|
15
|
+
qdrant_host: str = Field(default="localhost", description="Qdrant hostname")
|
|
16
|
+
qdrant_port: int = Field(default=6333, description="Qdrant port")
|
|
17
|
+
collection: str = Field(default="flock_memories", description="Vector collection")
|
|
18
|
+
embedder_provider: str = Field(default="openai", description="'openai' or 'local'")
|
|
19
|
+
embedder_model: str = Field(default="text-embedding-ada-002",
|
|
20
|
+
description="Model name for embeddings")
|
|
21
|
+
# Optional: allow separate LLM for reflection/summarisation
|
|
22
|
+
llm_provider: str | None = Field(default=None)
|
|
23
|
+
llm_model: str | None = Field(default=None)
|
|
24
|
+
top_k: int = Field(default=5, description="Number of memories to retrieve")
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
@flock_component(config_class=Mem0ModuleConfig)
|
|
29
|
+
class Mem0Module(FlockModule):
|
|
30
|
+
"""Module that adds Zep capabilities to a Flock agent."""
|
|
31
|
+
|
|
32
|
+
name: str = "mem0"
|
|
33
|
+
config: Mem0ModuleConfig = Mem0ModuleConfig()
|
|
34
|
+
session_id: str | None = None
|
|
35
|
+
user_id: str | None = None
|
|
36
|
+
|
|
37
|
+
def __init__(self, name, config: Mem0ModuleConfig) -> None:
|
|
38
|
+
"""Initialize Mem0 module."""
|
|
39
|
+
super().__init__(name=name, config=config)
|
|
40
|
+
logger.debug("Initializing Mem0 module")
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
async def on_post_evaluate(
|
|
44
|
+
self,
|
|
45
|
+
agent: FlockAgent,
|
|
46
|
+
inputs: dict[str, Any],
|
|
47
|
+
context: FlockContext | None = None,
|
|
48
|
+
result: dict[str, Any] | None = None,
|
|
49
|
+
) -> dict[str, Any]:
|
|
50
|
+
|
|
51
|
+
return result
|
|
52
|
+
|
|
53
|
+
async def on_pre_evaluate(
|
|
54
|
+
self,
|
|
55
|
+
agent: FlockAgent,
|
|
56
|
+
inputs: dict[str, Any],
|
|
57
|
+
context: FlockContext | None = None,
|
|
58
|
+
) -> dict[str, Any]:
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
return inputs
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
# Package for modules
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
from typing import Any
|
|
2
|
+
|
|
3
|
+
from pydantic import Field
|
|
4
|
+
|
|
5
|
+
from flock.core.context.context import FlockContext
|
|
6
|
+
from flock.core.flock_agent import FlockAgent
|
|
7
|
+
from flock.core.flock_module import FlockModule, FlockModuleConfig
|
|
8
|
+
from flock.core.flock_registry import flock_component
|
|
9
|
+
from flock.core.logging.logging import get_logger
|
|
10
|
+
|
|
11
|
+
logger = get_logger("module.mem0")
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class Mem0GraphModuleConfig(FlockModuleConfig):
|
|
15
|
+
qdrant_host: str = Field(default="localhost", description="Qdrant hostname")
|
|
16
|
+
qdrant_port: int = Field(default=6333, description="Qdrant port")
|
|
17
|
+
collection: str = Field(default="flock_memories", description="Vector collection")
|
|
18
|
+
embedder_provider: str = Field(default="openai", description="'openai' or 'local'")
|
|
19
|
+
embedder_model: str = Field(default="text-embedding-ada-002",
|
|
20
|
+
description="Model name for embeddings")
|
|
21
|
+
# Optional: allow separate LLM for reflection/summarisation
|
|
22
|
+
llm_provider: str | None = Field(default=None)
|
|
23
|
+
llm_model: str | None = Field(default=None)
|
|
24
|
+
top_k: int = Field(default=5, description="Number of memories to retrieve")
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
@flock_component(config_class=Mem0GraphModuleConfig)
|
|
29
|
+
class Mem0GraphModule(FlockModule):
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
name: str = "mem0"
|
|
33
|
+
config: Mem0GraphModuleConfig = Mem0GraphModuleConfig()
|
|
34
|
+
session_id: str | None = None
|
|
35
|
+
user_id: str | None = None
|
|
36
|
+
|
|
37
|
+
def __init__(self, name, config: Mem0GraphModuleConfig) -> None:
|
|
38
|
+
"""Initialize Mem0 module."""
|
|
39
|
+
super().__init__(name=name, config=config)
|
|
40
|
+
logger.debug("Initializing Mem0 module")
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
async def on_post_evaluate(
|
|
44
|
+
self,
|
|
45
|
+
agent: FlockAgent,
|
|
46
|
+
inputs: dict[str, Any],
|
|
47
|
+
context: FlockContext | None = None,
|
|
48
|
+
result: dict[str, Any] | None = None,
|
|
49
|
+
) -> dict[str, Any]:
|
|
50
|
+
|
|
51
|
+
return result
|
|
52
|
+
|
|
53
|
+
async def on_pre_evaluate(
|
|
54
|
+
self,
|
|
55
|
+
agent: FlockAgent,
|
|
56
|
+
inputs: dict[str, Any],
|
|
57
|
+
context: FlockContext | None = None,
|
|
58
|
+
) -> dict[str, Any]:
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
return inputs
|
|
@@ -1,9 +1,14 @@
|
|
|
1
1
|
# src/flock/webapp/app/api/execution.py
|
|
2
2
|
import json
|
|
3
3
|
from pathlib import Path
|
|
4
|
-
from typing import TYPE_CHECKING
|
|
4
|
+
from typing import TYPE_CHECKING, Any
|
|
5
5
|
|
|
6
|
-
from fastapi import
|
|
6
|
+
from fastapi import ( # Ensure Form and HTTPException are imported
|
|
7
|
+
APIRouter,
|
|
8
|
+
Depends,
|
|
9
|
+
Form,
|
|
10
|
+
Request,
|
|
11
|
+
)
|
|
7
12
|
from fastapi.responses import HTMLResponse
|
|
8
13
|
from fastapi.templating import Jinja2Templates
|
|
9
14
|
|
|
@@ -11,6 +16,12 @@ if TYPE_CHECKING:
|
|
|
11
16
|
from flock.core.flock import Flock
|
|
12
17
|
|
|
13
18
|
|
|
19
|
+
from flock.core.flock import (
|
|
20
|
+
Flock as ConcreteFlock, # For creating Flock instance
|
|
21
|
+
)
|
|
22
|
+
from flock.core.logging.logging import (
|
|
23
|
+
get_logger as get_flock_logger, # For logging within the new endpoint
|
|
24
|
+
)
|
|
14
25
|
from flock.core.util.spliter import parse_schema
|
|
15
26
|
|
|
16
27
|
# Import the dependency to get the current Flock instance
|
|
@@ -97,19 +108,23 @@ async def htmx_run_flock(
|
|
|
97
108
|
# We retrieve current_flock from app_state inside the service or before calling if needed for validation here
|
|
98
109
|
|
|
99
110
|
# It's better to get flock from app_state here to validate before calling service
|
|
100
|
-
|
|
111
|
+
current_flock_from_state: Flock | None = getattr(request.app.state, 'flock_instance', None)
|
|
112
|
+
logger = get_flock_logger("webapp.execution.regular_run") # Standard logger
|
|
101
113
|
|
|
102
|
-
if not
|
|
114
|
+
if not current_flock_from_state:
|
|
115
|
+
logger.error("HTMX Run (Regular): No Flock loaded in app_state.")
|
|
103
116
|
return HTMLResponse("<p class='error'>No Flock loaded to run.</p>")
|
|
104
117
|
|
|
105
118
|
form_data = await request.form()
|
|
106
119
|
start_agent_name = form_data.get("start_agent_name")
|
|
107
120
|
|
|
108
121
|
if not start_agent_name:
|
|
122
|
+
logger.warning("HTMX Run (Regular): Starting agent not selected.")
|
|
109
123
|
return HTMLResponse("<p class='error'>Starting agent not selected.</p>")
|
|
110
124
|
|
|
111
|
-
agent =
|
|
125
|
+
agent = current_flock_from_state.agents.get(start_agent_name)
|
|
112
126
|
if not agent:
|
|
127
|
+
logger.error(f"HTMX Run (Regular): Agent '{start_agent_name}' not found in Flock '{current_flock_from_state.name}'.")
|
|
113
128
|
return HTMLResponse(
|
|
114
129
|
f"<p class='error'>Agent '{start_agent_name}' not found in the current Flock.</p>"
|
|
115
130
|
)
|
|
@@ -119,46 +134,131 @@ async def htmx_run_flock(
|
|
|
119
134
|
try:
|
|
120
135
|
parsed_spec = parse_schema(agent.input)
|
|
121
136
|
for name, type_str, _ in parsed_spec:
|
|
122
|
-
form_field_name = f"agent_input_{name}"
|
|
137
|
+
form_field_name = f"agent_input_{name}"
|
|
123
138
|
raw_value = form_data.get(form_field_name)
|
|
124
|
-
|
|
125
139
|
if raw_value is None and "bool" in type_str.lower(): inputs[name] = False; continue
|
|
126
140
|
if raw_value is None: inputs[name] = None; continue
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
elif "float" in type_str.lower():
|
|
132
|
-
try: inputs[name] = float(raw_value)
|
|
133
|
-
except ValueError: return HTMLResponse(f"<p class='error'>Invalid float for '{name}'.</p>")
|
|
134
|
-
elif "bool" in type_str.lower():
|
|
135
|
-
inputs[name] = raw_value.lower() in ["true", "on", "1", "yes"]
|
|
136
|
-
elif "list" in type_str.lower() or "dict" in type_str.lower():
|
|
137
|
-
try: inputs[name] = json.loads(raw_value)
|
|
138
|
-
except json.JSONDecodeError: return HTMLResponse(f"<p class='error'>Invalid JSON for '{name}'.</p>")
|
|
141
|
+
if "int" in type_str.lower(): inputs[name] = int(raw_value)
|
|
142
|
+
elif "float" in type_str.lower(): inputs[name] = float(raw_value)
|
|
143
|
+
elif "bool" in type_str.lower(): inputs[name] = raw_value.lower() in ["true", "on", "1", "yes"]
|
|
144
|
+
elif "list" in type_str.lower() or "dict" in type_str.lower(): inputs[name] = json.loads(raw_value)
|
|
139
145
|
else: inputs[name] = raw_value
|
|
140
|
-
except
|
|
141
|
-
|
|
146
|
+
except ValueError as ve:
|
|
147
|
+
logger.error(f"HTMX Run (Regular): Input parsing error for agent '{start_agent_name}': {ve}", exc_info=True)
|
|
148
|
+
return HTMLResponse(f"<p class='error'>Invalid input format: {ve!s}</p>")
|
|
149
|
+
except Exception as e_parse:
|
|
150
|
+
logger.error(f"HTMX Run (Regular): Error processing inputs for '{start_agent_name}': {e_parse}", exc_info=True)
|
|
151
|
+
return HTMLResponse(f"<p class='error'>Error processing inputs for {start_agent_name}: {e_parse}</p>")
|
|
142
152
|
|
|
143
153
|
try:
|
|
144
|
-
|
|
154
|
+
logger.info(f"HTMX Run (Regular): Executing agent '{start_agent_name}' from Flock '{current_flock_from_state.name}' via service.")
|
|
145
155
|
result_data = await run_current_flock_service(start_agent_name, inputs, request.app.state)
|
|
156
|
+
except Exception as e_run:
|
|
157
|
+
logger.error(f"HTMX Run (Regular): Error during service execution for '{start_agent_name}': {e_run}", exc_info=True)
|
|
158
|
+
return templates.TemplateResponse(
|
|
159
|
+
"partials/_results_display.html",
|
|
160
|
+
{"request": request, "result_data": {"error": f"Error during execution: {e_run!s}"}},
|
|
161
|
+
)
|
|
162
|
+
|
|
163
|
+
# Process and serialize result for template
|
|
164
|
+
try:
|
|
165
|
+
processed_result = pydantic_to_dict(result_data)
|
|
166
|
+
try: json.dumps(processed_result)
|
|
167
|
+
except (TypeError, ValueError) as ser_e:
|
|
168
|
+
processed_result = f"Error: Result contains non-serializable data: {ser_e!s}\nOriginal result preview: {str(result_data)[:500]}..."
|
|
169
|
+
logger.warning(f"HTMX Run (Regular): Serialization issue: {processed_result}")
|
|
170
|
+
except Exception as proc_e:
|
|
171
|
+
processed_result = f"Error: Failed to process result data: {proc_e!s}"
|
|
172
|
+
logger.error(f"HTMX Run (Regular): Result processing error: {processed_result}", exc_info=True)
|
|
173
|
+
|
|
174
|
+
return templates.TemplateResponse(
|
|
175
|
+
"partials/_results_display.html",
|
|
176
|
+
{"request": request, "result_data": processed_result},
|
|
177
|
+
)
|
|
178
|
+
|
|
179
|
+
|
|
180
|
+
# --- NEW ENDPOINT FOR SHARED RUNS ---
|
|
181
|
+
@router.post("/htmx/run-shared", response_class=HTMLResponse)
|
|
182
|
+
async def htmx_run_shared_flock(
|
|
183
|
+
request: Request,
|
|
184
|
+
share_id: str = Form(...), # Expect share_id from the form
|
|
185
|
+
# flock_definition_str: str = Form(...), # No longer needed
|
|
186
|
+
# start_agent_name from form is still required implicitly via form_data.get()
|
|
187
|
+
# No DI for current_flock, as we are using the one from app.state via share_id
|
|
188
|
+
):
|
|
189
|
+
shared_logger = get_flock_logger("webapp.execution.shared_run_stateful")
|
|
190
|
+
form_data = await request.form()
|
|
191
|
+
start_agent_name = form_data.get("start_agent_name")
|
|
146
192
|
|
|
193
|
+
if not start_agent_name:
|
|
194
|
+
shared_logger.warning("HTMX Run Shared (Stateful): Starting agent name not provided in form.")
|
|
195
|
+
return HTMLResponse("<p class='error'>Critical error: Starting agent name missing from shared run form.</p>")
|
|
196
|
+
|
|
197
|
+
shared_logger.info(f"HTMX Run Shared (Stateful): Attempting to execute agent '{start_agent_name}' using pre-loaded Flock for share_id '{share_id}'.")
|
|
198
|
+
|
|
199
|
+
inputs = {}
|
|
200
|
+
result_data: Any = None
|
|
201
|
+
temp_flock: ConcreteFlock | None = None
|
|
202
|
+
|
|
203
|
+
try:
|
|
204
|
+
# Retrieve the pre-loaded Flock instance from app.state
|
|
205
|
+
shared_flocks_store = getattr(request.app.state, 'shared_flocks', {})
|
|
206
|
+
temp_flock = shared_flocks_store.get(share_id)
|
|
207
|
+
|
|
208
|
+
if not temp_flock:
|
|
209
|
+
shared_logger.error(f"HTMX Run Shared: Flock instance for share_id '{share_id}' not found in app.state.")
|
|
210
|
+
return HTMLResponse(f"<p class='error'>Shared session not found or expired. Please try accessing the shared link again.</p>")
|
|
211
|
+
|
|
212
|
+
shared_logger.info(f"HTMX Run Shared: Successfully retrieved pre-loaded Flock '{temp_flock.name}' for agent '{start_agent_name}' (share_id: {share_id}).")
|
|
213
|
+
|
|
214
|
+
agent = temp_flock.agents.get(start_agent_name)
|
|
215
|
+
if not agent:
|
|
216
|
+
shared_logger.error(f"HTMX Run Shared: Agent '{start_agent_name}' not found in shared Flock '{temp_flock.name}'.")
|
|
217
|
+
return HTMLResponse(f"<p class='error'>Agent '{start_agent_name}' not found in the provided shared Flock definition.</p>")
|
|
218
|
+
|
|
219
|
+
# Parse inputs for the agent from the temporary flock
|
|
220
|
+
if agent.input and isinstance(agent.input, str):
|
|
221
|
+
parsed_spec = parse_schema(agent.input)
|
|
222
|
+
for name, type_str, _ in parsed_spec:
|
|
223
|
+
form_field_name = f"agent_input_{name}" # Name used in shared_run_page.html
|
|
224
|
+
raw_value = form_data.get(form_field_name)
|
|
225
|
+
|
|
226
|
+
# Input type conversion (consistent with the other endpoint)
|
|
227
|
+
if raw_value is None and "bool" in type_str.lower(): inputs[name] = False; continue
|
|
228
|
+
if raw_value is None: inputs[name] = None; continue
|
|
229
|
+
if "int" in type_str.lower(): inputs[name] = int(raw_value)
|
|
230
|
+
elif "float" in type_str.lower(): inputs[name] = float(raw_value)
|
|
231
|
+
elif "bool" in type_str.lower(): inputs[name] = raw_value.lower() in ["true", "on", "1", "yes"]
|
|
232
|
+
elif "list" in type_str.lower() or "dict" in type_str.lower(): inputs[name] = json.loads(raw_value)
|
|
233
|
+
else: inputs[name] = raw_value
|
|
234
|
+
|
|
235
|
+
shared_logger.info(f"HTMX Run Shared: Executing agent '{start_agent_name}' in pre-loaded Flock '{temp_flock.name}'. Inputs: {list(inputs.keys())}")
|
|
236
|
+
result_data = await temp_flock.run_async(start_agent=start_agent_name, input=inputs, box_result=False)
|
|
237
|
+
shared_logger.info(f"HTMX Run Shared: Agent '{start_agent_name}' executed. Result keys: {list(result_data.keys()) if isinstance(result_data, dict) else 'N/A'}")
|
|
238
|
+
|
|
239
|
+
# Process and serialize result for template (same logic as other endpoint)
|
|
147
240
|
try:
|
|
148
|
-
|
|
149
|
-
try: json.dumps(
|
|
241
|
+
processed_result = pydantic_to_dict(result_data)
|
|
242
|
+
try: json.dumps(processed_result)
|
|
150
243
|
except (TypeError, ValueError) as ser_e:
|
|
151
|
-
|
|
244
|
+
processed_result = f"Error: Result contains non-serializable data: {ser_e!s}\nOriginal result preview: {str(result_data)[:500]}..."
|
|
245
|
+
shared_logger.warning(f"HTMX Run Shared: Serialization issue: {processed_result}")
|
|
152
246
|
except Exception as proc_e:
|
|
153
|
-
|
|
247
|
+
processed_result = f"Error: Failed to process result data: {proc_e!s}"
|
|
248
|
+
shared_logger.error(f"HTMX Run Shared: Result processing error: {processed_result}", exc_info=True)
|
|
154
249
|
|
|
155
250
|
return templates.TemplateResponse(
|
|
156
251
|
"partials/_results_display.html",
|
|
157
|
-
{"request": request, "result_data":
|
|
252
|
+
{"request": request, "result_data": processed_result},
|
|
158
253
|
)
|
|
159
|
-
|
|
160
|
-
|
|
254
|
+
|
|
255
|
+
except ValueError as ve: # Catch specific input parsing errors
|
|
256
|
+
shared_logger.error(f"HTMX Run Shared: Input parsing error for agent '{start_agent_name}': {ve}", exc_info=True)
|
|
257
|
+
return HTMLResponse(f"<p class='error'>Invalid input format: {ve!s}</p>")
|
|
258
|
+
except Exception as e_general:
|
|
259
|
+
error_message = f"An unexpected error occurred during shared execution: {e_general!s}"
|
|
260
|
+
shared_logger.error(f"HTMX Run Shared: General error for agent '{start_agent_name}': {e_general}", exc_info=True)
|
|
161
261
|
return templates.TemplateResponse(
|
|
162
262
|
"partials/_results_display.html",
|
|
163
|
-
{"request": request, "result_data":
|
|
263
|
+
{"request": request, "result_data": {"error": error_message } },
|
|
164
264
|
)
|