flock-core 0.4.0b49__py3-none-any.whl → 0.4.0b50__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.

@@ -3,6 +3,7 @@ import json
3
3
  from pathlib import Path
4
4
  from typing import TYPE_CHECKING, Any
5
5
 
6
+ import markdown2 # Import markdown2
6
7
  from fastapi import ( # Ensure Form and HTTPException are imported
7
8
  APIRouter,
8
9
  Depends,
@@ -16,9 +17,6 @@ if TYPE_CHECKING:
16
17
  from flock.core.flock import Flock
17
18
 
18
19
 
19
- from flock.core.flock import (
20
- Flock as ConcreteFlock, # For creating Flock instance
21
- )
22
20
  from flock.core.logging.logging import (
23
21
  get_logger as get_flock_logger, # For logging within the new endpoint
24
22
  )
@@ -35,12 +33,17 @@ from flock.webapp.app.services.flock_service import (
35
33
  run_current_flock_service,
36
34
  # get_current_flock_instance IS NO LONGER IMPORTED
37
35
  )
38
- from flock.webapp.app.utils import pydantic_to_dict
39
36
 
40
37
  router = APIRouter()
41
38
  BASE_DIR = Path(__file__).resolve().parent.parent.parent
42
39
  templates = Jinja2Templates(directory=str(BASE_DIR / "templates"))
43
40
 
41
+ # Add markdown2 filter to Jinja2 environment for this router
42
+ def markdown_filter(text):
43
+ return markdown2.markdown(text, extras=["tables", "fenced-code-blocks"])
44
+
45
+ templates.env.filters['markdown'] = markdown_filter
46
+
44
47
 
45
48
  @router.get("/htmx/execution-form-content", response_class=HTMLResponse)
46
49
  async def htmx_get_execution_form_content(
@@ -102,14 +105,9 @@ async def htmx_get_agent_input_form(
102
105
  @router.post("/htmx/run", response_class=HTMLResponse)
103
106
  async def htmx_run_flock(
104
107
  request: Request,
105
- # current_flock: Flock = Depends(get_flock_instance) # Service will use app_state
106
108
  ):
107
- # The service function run_current_flock_service now takes app_state
108
- # We retrieve current_flock from app_state inside the service or before calling if needed for validation here
109
-
110
- # It's better to get flock from app_state here to validate before calling service
111
109
  current_flock_from_state: Flock | None = getattr(request.app.state, 'flock_instance', None)
112
- logger = get_flock_logger("webapp.execution.regular_run") # Standard logger
110
+ logger = get_flock_logger("webapp.execution.regular_run")
113
111
 
114
112
  if not current_flock_from_state:
115
113
  logger.error("HTMX Run (Regular): No Flock loaded in app_state.")
@@ -150,30 +148,14 @@ async def htmx_run_flock(
150
148
  logger.error(f"HTMX Run (Regular): Error processing inputs for '{start_agent_name}': {e_parse}", exc_info=True)
151
149
  return HTMLResponse(f"<p class='error'>Error processing inputs for {start_agent_name}: {e_parse}</p>")
152
150
 
153
- try:
154
- logger.info(f"HTMX Run (Regular): Executing agent '{start_agent_name}' from Flock '{current_flock_from_state.name}' via service.")
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)
151
+ result_data = await run_current_flock_service(start_agent_name, inputs, request.app.state)
152
+ raw_json_for_template = json.dumps(result_data, indent=2)
153
+ # Unescape newlines for proper display in HTML <pre> tag
154
+ result_data_raw_json_str = raw_json_for_template.replace('\\n', '\n')
173
155
 
174
156
  return templates.TemplateResponse(
175
157
  "partials/_results_display.html",
176
- {"request": request, "result_data": processed_result},
158
+ {"request": request, "result": result_data, "result_raw_json": result_data_raw_json_str} # Pass both
177
159
  )
178
160
 
179
161
 
@@ -181,27 +163,18 @@ async def htmx_run_flock(
181
163
  @router.post("/htmx/run-shared", response_class=HTMLResponse)
182
164
  async def htmx_run_shared_flock(
183
165
  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
166
+ share_id: str = Form(...),
188
167
  ):
189
168
  shared_logger = get_flock_logger("webapp.execution.shared_run_stateful")
190
169
  form_data = await request.form()
191
170
  start_agent_name = form_data.get("start_agent_name")
192
171
 
193
172
  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
173
+ shared_logger.warning("HTMX Run Shared: Starting agent not selected.")
174
+ return HTMLResponse("<p class='error'>Starting agent not selected for shared run.</p>")
202
175
 
176
+ inputs: dict[str, Any] = {}
203
177
  try:
204
- # Retrieve the pre-loaded Flock instance from app.state
205
178
  shared_flocks_store = getattr(request.app.state, 'shared_flocks', {})
206
179
  temp_flock = shared_flocks_store.get(share_id)
207
180
 
@@ -216,14 +189,11 @@ async def htmx_run_shared_flock(
216
189
  shared_logger.error(f"HTMX Run Shared: Agent '{start_agent_name}' not found in shared Flock '{temp_flock.name}'.")
217
190
  return HTMLResponse(f"<p class='error'>Agent '{start_agent_name}' not found in the provided shared Flock definition.</p>")
218
191
 
219
- # Parse inputs for the agent from the temporary flock
220
192
  if agent.input and isinstance(agent.input, str):
221
193
  parsed_spec = parse_schema(agent.input)
222
194
  for name, type_str, _ in parsed_spec:
223
- form_field_name = f"agent_input_{name}" # Name used in shared_run_page.html
195
+ form_field_name = f"agent_input_{name}"
224
196
  raw_value = form_data.get(form_field_name)
225
-
226
- # Input type conversion (consistent with the other endpoint)
227
197
  if raw_value is None and "bool" in type_str.lower(): inputs[name] = False; continue
228
198
  if raw_value is None: inputs[name] = None; continue
229
199
  if "int" in type_str.lower(): inputs[name] = int(raw_value)
@@ -234,31 +204,19 @@ async def htmx_run_shared_flock(
234
204
 
235
205
  shared_logger.info(f"HTMX Run Shared: Executing agent '{start_agent_name}' in pre-loaded Flock '{temp_flock.name}'. Inputs: {list(inputs.keys())}")
236
206
  result_data = await temp_flock.run_async(start_agent=start_agent_name, input=inputs, box_result=False)
207
+ raw_json_for_template = json.dumps(result_data, indent=2)
208
+ # Unescape newlines for proper display in HTML <pre> tag
209
+ result_data_raw_json_str = raw_json_for_template.replace('\\n', '\n')
237
210
  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
211
 
239
- # Process and serialize result for template (same logic as other endpoint)
240
- try:
241
- processed_result = pydantic_to_dict(result_data)
242
- try: json.dumps(processed_result)
243
- except (TypeError, ValueError) as ser_e:
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}")
246
- except Exception as proc_e:
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)
249
-
250
- return templates.TemplateResponse(
251
- "partials/_results_display.html",
252
- {"request": request, "result_data": processed_result},
253
- )
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)
212
+ except ValueError as ve:
213
+ shared_logger.error(f"HTMX Run Shared: Input parsing error for '{start_agent_name}' (share_id: {share_id}): {ve}", exc_info=True)
257
214
  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)
261
- return templates.TemplateResponse(
262
- "partials/_results_display.html",
263
- {"request": request, "result_data": {"error": error_message } },
264
- )
215
+ except Exception as e:
216
+ shared_logger.error(f"HTMX Run Shared: Error during execution for '{start_agent_name}' (share_id: {share_id}): {e}", exc_info=True)
217
+ return HTMLResponse(f"<p class='error'>An unexpected error occurred: {e!s}</p>")
218
+
219
+ return templates.TemplateResponse(
220
+ "partials/_results_display.html",
221
+ {"request": request, "result": result_data, "result_raw_json": result_data_raw_json_str} # Pass both
222
+ )
flock/webapp/app/chat.py CHANGED
@@ -6,7 +6,7 @@ from datetime import datetime
6
6
  from uuid import uuid4
7
7
 
8
8
  import markdown2 # Added for Markdown to HTML conversion
9
- from fastapi import APIRouter, Depends, Form, Request
9
+ from fastapi import APIRouter, Depends, Form, Request, Response
10
10
  from fastapi.responses import HTMLResponse
11
11
  from pydantic import BaseModel
12
12
 
@@ -272,7 +272,7 @@ async def chat_settings_form(request: Request):
272
272
  return templates.TemplateResponse("partials/_chat_settings_form.html", context)
273
273
 
274
274
 
275
- @router.post("/chat/settings", response_class=HTMLResponse, include_in_schema=False)
275
+ @router.post("/chat/settings", include_in_schema=False)
276
276
  async def chat_settings_submit(
277
277
  request: Request,
278
278
  agent_name: str | None = Form(default=None),
@@ -280,19 +280,23 @@ async def chat_settings_submit(
280
280
  history_key: str = Form("history"),
281
281
  response_key: str = Form("response"),
282
282
  ):
283
- """Apply submitted chat config, then re-render the form with a success message."""
283
+ """Handles chat settings submission and triggers a toast notification."""
284
284
  cfg = get_chat_config(request)
285
- cfg.agent_name = agent_name or None
285
+ cfg.agent_name = agent_name
286
286
  cfg.message_key = message_key
287
287
  cfg.history_key = history_key
288
288
  cfg.response_key = response_key
289
289
 
290
- headers = {
291
- "HX-Trigger": json.dumps({"notify": {"type": "success", "message": "Chat settings saved"}}),
292
- "HX-Redirect": "/chat"
290
+ logger.info(f"Chat settings updated: Agent: {cfg.agent_name}, MsgKey: {cfg.message_key}, HistKey: {cfg.history_key}, RespKey: {cfg.response_key}")
291
+
292
+ toast_event = {
293
+ "showGlobalToast": {
294
+ "message": "Chat settings saved successfully!",
295
+ "type": "success"
296
+ }
293
297
  }
294
- # Response body empty; HTMX will redirect
295
- return HTMLResponse("", headers=headers)
298
+ headers = {"HX-Trigger": json.dumps(toast_event)}
299
+ return Response(status_code=204, headers=headers)
296
300
 
297
301
 
298
302
  # --- Stand-alone Chat HTML page access to settings --------------------------
@@ -38,7 +38,7 @@ THEMES_DIR = FLOCK_BASE_DIR / "themes"
38
38
  CURRENT_FLOCK_INSTANCE: "Flock | None" = None
39
39
  CURRENT_FLOCK_FILENAME: str | None = None
40
40
 
41
- DEFAULT_THEME_NAME = OutputTheme.everblush.value # Default if random fails or invalid theme specified
41
+ DEFAULT_THEME_NAME = OutputTheme.ciapre.value # Default if random fails or invalid theme specified
42
42
 
43
43
  def list_available_themes() -> list[str]:
44
44
  """Scans the THEMES_DIR for .toml files and returns their names (without .toml)."""
flock/webapp/app/main.py CHANGED
@@ -9,6 +9,7 @@ import uuid
9
9
  from contextlib import asynccontextmanager
10
10
  from pathlib import Path
11
11
 
12
+ import markdown2 # Import markdown2
12
13
  from fastapi import (
13
14
  Depends,
14
15
  FastAPI,
@@ -237,6 +238,12 @@ BASE_DIR = Path(__file__).resolve().parent.parent
237
238
  app.mount("/static", StaticFiles(directory=str(BASE_DIR / "static")), name="static")
238
239
  templates = Jinja2Templates(directory=str(BASE_DIR / "templates"))
239
240
 
241
+ # Add markdown2 filter to Jinja2 environment
242
+ def markdown_filter(text):
243
+ return markdown2.markdown(text, extras=["tables", "fenced-code-blocks"])
244
+
245
+ templates.env.filters['markdown'] = markdown_filter
246
+
240
247
  core_api_router = create_api_router()
241
248
  app.include_router(core_api_router, prefix="/api", tags=["Flock API Core"])
242
249
  app.include_router(flock_management.router, prefix="/ui/api/flock", tags=["UI Flock Management"])
@@ -758,11 +765,10 @@ async def ui_load_flock_by_name_action(request: Request, selected_flock_filename
758
765
  ui_mode_query = request.query_params.get("ui_mode", "standalone")
759
766
  if loaded_flock:
760
767
  success_message_text = f"Flock '{loaded_flock.name}' loaded from '{selected_flock_filename}'."
761
- response_headers["HX-Push-Url"] = "/ui/editor/properties?ui_mode=" + request.query_params.get("ui_mode", "standalone")
768
+ response_headers["HX-Push-Url"] = "/ui/editor/execute?ui_mode=" + ui_mode_query
762
769
  response_headers["HX-Trigger"] = json.dumps({"flockLoaded": None, "notify": {"type": "success", "message": success_message_text}})
763
- # Use get_base_context_web to ensure all necessary context vars are present for the partial
764
770
  context = get_base_context_web(request, success=success_message_text, ui_mode=ui_mode_query)
765
- return templates.TemplateResponse("partials/_flock_properties_form.html", context, headers=response_headers)
771
+ return templates.TemplateResponse("partials/_execution_view_container.html", context, headers=response_headers)
766
772
  else:
767
773
  error_message_text = f"Failed to load flock file '{selected_flock_filename}'."
768
774
  response_headers["HX-Trigger"] = json.dumps({"notify": {"type": "error", "message": error_message_text}})
@@ -790,16 +796,14 @@ async def ui_load_flock_by_upload_action(request: Request, flock_file_upload: Up
790
796
  loaded_flock = load_flock_from_file_service(filename_to_load, request.app.state)
791
797
  if loaded_flock:
792
798
  success_message_text = f"Flock '{loaded_flock.name}' loaded from '{filename_to_load}'."
793
- response_headers["HX-Push-Url"] = f"/ui/editor/properties?ui_mode={ui_mode_query}"
799
+ response_headers["HX-Push-Url"] = f"/ui/editor/execute?ui_mode={ui_mode_query}"
794
800
  response_headers["HX-Trigger"] = json.dumps({"flockLoaded": None, "flockFileListChanged": None, "notify": {"type": "success", "message": success_message_text}})
795
- # CORRECTED CALL:
796
801
  context = get_base_context_web(request, success=success_message_text, ui_mode=ui_mode_query)
797
- return templates.TemplateResponse("partials/_flock_properties_form.html", context, headers=response_headers)
802
+ return templates.TemplateResponse("partials/_execution_view_container.html", context, headers=response_headers)
798
803
  else: error_message_text = f"Failed to process uploaded '{filename_to_load}'."
799
804
 
800
805
  final_error_msg = error_message_text or "Upload failed."
801
806
  response_headers["HX-Trigger"] = json.dumps({"notify": {"type": "error", "message": final_error_msg}})
802
- # CORRECTED CALL:
803
807
  context = get_base_context_web(request, error=final_error_msg, ui_mode=ui_mode_query)
804
808
  return templates.TemplateResponse("partials/_create_flock_form.html", context, headers=response_headers)
805
809
 
@@ -807,16 +811,14 @@ async def ui_load_flock_by_upload_action(request: Request, flock_file_upload: Up
807
811
  async def ui_create_flock_action(request: Request, flock_name: str = Form(...), default_model: str = Form(None), description: str = Form(None)):
808
812
  ui_mode_query = request.query_params.get("ui_mode", "standalone")
809
813
  if not flock_name.strip():
810
- # CORRECTED CALL:
811
814
  context = get_base_context_web(request, error="Flock name cannot be empty.", ui_mode=ui_mode_query)
812
815
  return templates.TemplateResponse("partials/_create_flock_form.html", context)
813
816
 
814
817
  new_flock = create_new_flock_service(flock_name, default_model, description, request.app.state)
815
- success_msg_text = f"New flock '{new_flock.name}' created. Configure properties and save."
816
- response_headers = {"HX-Push-Url": f"/ui/editor/properties?ui_mode={ui_mode_query}", "HX-Trigger": json.dumps({"flockLoaded": None, "notify": {"type": "success", "message": success_msg_text}})}
817
- # CORRECTED CALL:
818
+ success_msg_text = f"New flock '{new_flock.name}' created. Navigating to Execute page. Configure properties and agents as needed."
819
+ response_headers = {"HX-Push-Url": f"/ui/editor/execute?ui_mode={ui_mode_query}", "HX-Trigger": json.dumps({"flockLoaded": None, "notify": {"type": "success", "message": success_msg_text}})}
818
820
  context = get_base_context_web(request, success=success_msg_text, ui_mode=ui_mode_query)
819
- return templates.TemplateResponse("partials/_flock_properties_form.html", context, headers=response_headers)
821
+ return templates.TemplateResponse("partials/_execution_view_container.html", context, headers=response_headers)
820
822
 
821
823
  # --- Settings Page & Endpoints ---
822
824
  @app.get("/ui/settings", response_class=HTMLResponse, tags=["UI Pages"])
@@ -14,8 +14,10 @@
14
14
  <link rel="stylesheet" href="/static/css/chat.css">
15
15
  <!-- Font Awesome for icons -->
16
16
  <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.1/css/all.min.css">
17
+ <!-- Prism.js CSS for syntax highlighting (okaidia theme) -->
18
+ <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/prism/1.29.0/themes/prism-okaidia.min.css" referrerpolicy="no-referrer" />
17
19
  {# Inject Theme CSS Variables #}
18
- {% if theme_css %}
20
+ {% if theme_css and theme_css.strip() %}
19
21
  <style>
20
22
  /* Start Theme CSS */
21
23
  {{ theme_css | safe }}
@@ -27,10 +29,17 @@
27
29
  integrity="sha384-D1Kt99CQMDuVetoL1lrYwg5t+9QdHe7NLX/SoJYkXDFfX37iInKRy5xLSi8nO7UC"
28
30
  crossorigin="anonymous"></script>
29
31
  <script defer src="https://cdn.jsdelivr.net/npm/alpinejs@3.x.x/dist/cdn.min.js"></script>
32
+ <!-- Prism.js JS (core and autoloader) -->
33
+ <script src="https://cdnjs.cloudflare.com/ajax/libs/prism/1.29.0/components/prism-core.min.js" referrerpolicy="no-referrer"></script>
34
+ <script src="https://cdnjs.cloudflare.com/ajax/libs/prism/1.29.0/plugins/autoloader/prism-autoloader.min.js" referrerpolicy="no-referrer"></script>
30
35
  <!-- Removed inline styles as they're in custom.css -->
31
36
  </head>
32
37
 
33
38
  <body>
39
+ <div id="global-toast-container" style="position: fixed; top: 1rem; right: 1rem; z-index: 9999; display: flex; flex-direction: column; gap: 0.5rem;">
40
+ <!-- Toasts will be appended here -->
41
+ </div>
42
+
34
43
  <header class="top-header">
35
44
  <span><strong>🐧 Flock Playground 🐤</strong></span>
36
45
  <span id="header-flock-status-container" hx-get="/ui/htmx/header-flock-status?ui_mode={{ ui_mode }}"
@@ -104,6 +113,87 @@
104
113
  function triggerEvent(eventName, detail = {}) {
105
114
  htmx.trigger(document.body, eventName, detail);
106
115
  }
116
+
117
+ // Add HTMX event listener for Prism highlighting
118
+ document.addEventListener('htmx:afterSwap', function(event) {
119
+ // Check if the swapped element or its parent is the main content area or results display
120
+ const mainContentArea = document.getElementById('main-content-area');
121
+ const resultsDisplay = document.getElementById('results-display-content');
122
+ let targetElement = event.detail.target;
123
+
124
+ if (targetElement === mainContentArea || (resultsDisplay && resultsDisplay.contains(targetElement)) || (mainContentArea && mainContentArea.contains(targetElement))) {
125
+ if (typeof Prism !== 'undefined') {
126
+ // console.log('Prism highlighting triggered for swapped content in main area.');
127
+ Prism.highlightAllUnder(mainContentArea || document.documentElement);
128
+ }
129
+ }
130
+ });
131
+
132
+ // Initial highlight on page load
133
+ document.addEventListener('DOMContentLoaded', () => {
134
+ if (typeof Prism !== 'undefined') {
135
+ // console.log('Prism initial highlighting.');
136
+ Prism.highlightAll();
137
+ }
138
+ });
139
+ </script>
140
+ {# Global Toast Handler - identical to the one in chat.html #}
141
+ <script>
142
+ document.body.addEventListener('showGlobalToast', function (event) {
143
+ const detail = event.detail;
144
+ const message = detail.message || 'Done!';
145
+ const type = detail.type || 'info'; // success, error, warning, info
146
+
147
+ const toastContainer = document.getElementById('global-toast-container');
148
+ if (!toastContainer) return;
149
+
150
+ const toast = document.createElement('article');
151
+ toast.className = `toast-message ${type}`;
152
+ toast.innerHTML = `<button class="close-toast" style="float: right; background: none; border: none; font-size: 1.2rem; line-height: 1; padding: 0.25rem 0.5rem; cursor: pointer;">&times;</button>${message}`;
153
+
154
+ toast.style.padding = '0.75rem';
155
+ toast.style.border = '1px solid';
156
+ toast.style.borderRadius = 'var(--pico-border-radius, 4px)';
157
+ toast.style.minWidth = '250px';
158
+ toast.style.maxWidth = '400px';
159
+ toast.style.opacity = '0';
160
+ toast.style.transition = 'opacity 0.3s ease-in-out, transform 0.3s ease-in-out';
161
+ toast.style.transform = 'translateX(100%)';
162
+
163
+ if (type === 'success') {
164
+ toast.style.borderColor = 'var(--pico-color-green-500, green)';
165
+ toast.style.backgroundColor = 'var(--pico-color-green-150, #e6fffa)';
166
+ toast.style.color = 'var(--pico-color-green-700, darkgreen)';
167
+ } else if (type === 'error') {
168
+ toast.style.borderColor = 'var(--pico-color-red-500, red)';
169
+ toast.style.backgroundColor = 'var(--pico-color-red-150, #ffe6e6)';
170
+ toast.style.color = 'var(--pico-color-red-700, darkred)';
171
+ } else { // Default/info/warning
172
+ toast.style.borderColor = 'var(--pico-color-blue-500, blue)';
173
+ toast.style.backgroundColor = 'var(--pico-color-blue-150, #e6f7ff)';
174
+ toast.style.color = 'var(--pico-color-blue-700, darkblue)';
175
+ }
176
+
177
+ toastContainer.appendChild(toast);
178
+
179
+ setTimeout(() => {
180
+ toast.style.opacity = '1';
181
+ toast.style.transform = 'translateX(0)';
182
+ }, 10);
183
+
184
+ const closeButton = toast.querySelector('.close-toast');
185
+ closeButton.onclick = () => {
186
+ toast.style.opacity = '0';
187
+ toast.style.transform = 'translateY(-20px)';
188
+ setTimeout(() => toast.remove(), 300);
189
+ };
190
+
191
+ setTimeout(() => {
192
+ toast.style.opacity = '0';
193
+ toast.style.transform = 'translateY(-20px)';
194
+ setTimeout(() => toast.remove(), 300);
195
+ }, 5000);
196
+ });
107
197
  </script>
108
198
  </body>
109
199
 
@@ -9,7 +9,7 @@
9
9
  {# Prism.js CSS for syntax highlighting (okaidia theme) #}
10
10
  <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/prism/1.29.0/themes/prism-okaidia.min.css" referrerpolicy="no-referrer" />
11
11
  {# Inject active theme variables #}
12
- {% if theme_css %}
12
+ {% if theme_css and theme_css.strip() %}
13
13
  <style>
14
14
  /* Start Theme CSS */
15
15
  /* stylelint-disable */
@@ -24,6 +24,10 @@
24
24
  <script src="https://cdnjs.cloudflare.com/ajax/libs/prism/1.29.0/plugins/autoloader/prism-autoloader.min.js" referrerpolicy="no-referrer"></script>
25
25
  </head>
26
26
  <body class="chat-page">
27
+ <div id="global-toast-container" style="position: fixed; top: 1rem; right: 1rem; z-index: 9999; display: flex; flex-direction: column; gap: 0.5rem;">
28
+ <!-- Toasts will be appended here -->
29
+ </div>
30
+
27
31
  <div id="chat-container">
28
32
  <div class="chat-header" style="justify-content: space-between;">
29
33
  <hgroup>
@@ -86,6 +90,65 @@
86
90
  Prism.highlightAll();
87
91
  });
88
92
  })();
93
+
94
+ // Global Toast Handler
95
+ document.body.addEventListener('showGlobalToast', function (event) {
96
+ const detail = event.detail;
97
+ const message = detail.message || 'Done!';
98
+ const type = detail.type || 'info'; // success, error, warning, info
99
+
100
+ const toastContainer = document.getElementById('global-toast-container');
101
+ if (!toastContainer) return;
102
+
103
+ const toast = document.createElement('article');
104
+ toast.className = `toast-message ${type}`;
105
+ toast.innerHTML = `<button class="close-toast" style="float: right; background: none; border: none; font-size: 1.2rem; line-height: 1; padding: 0.25rem 0.5rem; cursor: pointer;">&times;</button>${message}`;
106
+
107
+ // Basic styling, can be enhanced in CSS file
108
+ toast.style.padding = '0.75rem';
109
+ toast.style.border = '1px solid';
110
+ toast.style.borderRadius = 'var(--pico-border-radius, 4px)';
111
+ toast.style.minWidth = '250px';
112
+ toast.style.maxWidth = '400px';
113
+ toast.style.opacity = '0'; // Start faded out
114
+ toast.style.transition = 'opacity 0.3s ease-in-out, transform 0.3s ease-in-out';
115
+ toast.style.transform = 'translateX(100%)'; // Start off-screen
116
+
117
+ if (type === 'success') {
118
+ toast.style.borderColor = 'var(--pico-color-green-500, green)';
119
+ toast.style.backgroundColor = 'var(--pico-color-green-150, #e6fffa)';
120
+ toast.style.color = 'var(--pico-color-green-700, darkgreen)';
121
+ } else if (type === 'error') {
122
+ toast.style.borderColor = 'var(--pico-color-red-500, red)';
123
+ toast.style.backgroundColor = 'var(--pico-color-red-150, #ffe6e6)';
124
+ toast.style.color = 'var(--pico-color-red-700, darkred)';
125
+ } else { // Default/info/warning
126
+ toast.style.borderColor = 'var(--pico-color-blue-500, blue)';
127
+ toast.style.backgroundColor = 'var(--pico-color-blue-150, #e6f7ff)';
128
+ toast.style.color = 'var(--pico-color-blue-700, darkblue)';
129
+ }
130
+
131
+ toastContainer.appendChild(toast);
132
+
133
+ // Animate in
134
+ setTimeout(() => {
135
+ toast.style.opacity = '1';
136
+ toast.style.transform = 'translateX(0)';
137
+ }, 10); // Small delay to allow CSS to apply initial state
138
+
139
+ const closeButton = toast.querySelector('.close-toast');
140
+ closeButton.onclick = () => {
141
+ toast.style.opacity = '0';
142
+ toast.style.transform = 'translateY(-20px)';
143
+ setTimeout(() => toast.remove(), 300);
144
+ };
145
+
146
+ setTimeout(() => {
147
+ toast.style.opacity = '0';
148
+ toast.style.transform = 'translateY(-20px)';
149
+ setTimeout(() => toast.remove(), 300);
150
+ }, 5000); // Auto-dismiss after 5 seconds
151
+ });
89
152
  </script>
90
153
  </body>
91
154
  </html>
@@ -14,9 +14,9 @@
14
14
  {% endif %}
15
15
 
16
16
  <form {% if is_new %}
17
- hx-post="/api/flock/htmx/agents"
17
+ hx-post="/ui/api/flock/htmx/agents"
18
18
  {% else %}
19
- hx-put="/api/flock/htmx/agents/{{ agent.name if agent else '' }}"
19
+ hx-put="/ui/api/flock/htmx/agents/{{ agent.name if agent else '' }}"
20
20
  {% endif %}
21
21
  hx-target="#agent-detail-form-content"
22
22
  hx-swap="innerHTML"
@@ -77,7 +77,7 @@
77
77
  </button>
78
78
  {% if not is_new and agent %}
79
79
  <button type="button" role="button" class="secondary outline"
80
- hx-delete="/api/flock/htmx/agents/{{ agent.name }}"
80
+ hx-delete="/ui/api/flock/htmx/agents/{{ agent.name }}"
81
81
  hx-target="#agent-detail-form-content"
82
82
  hx-confirm="Are you sure you want to delete agent '{{ agent.name }}'?"
83
83
  hx-indicator="#agent-detail-loading-indicator">
@@ -23,7 +23,7 @@
23
23
  </div>
24
24
  {% endif %}
25
25
 
26
- <form hx-post="/api/flock/htmx/flock-properties" hx-target="#flock-properties-form-article" hx-swap="innerHTML" hx-indicator="#flock-props-loading">
26
+ <form hx-post="/ui/api/flock/htmx/flock-properties" hx-target="#flock-properties-form-article" hx-swap="innerHTML" hx-indicator="#flock-props-loading">
27
27
  <label for="flock_name">Flock Name</label>
28
28
  <input type="text" id="flock_name" name="flock_name" value="{{ flock.name if flock else '' }}" required>
29
29
 
@@ -38,7 +38,7 @@
38
38
  </div>
39
39
  </form>
40
40
  <hr>
41
- <form hx-post="/api/flock/htmx/save-flock" hx-target="#flock-properties-form-article" hx-swap="innerHTML" hx-indicator="#flock-save-loading">
41
+ <form hx-post="/ui/api/flock/htmx/save-flock" hx-target="#flock-properties-form-article" hx-swap="innerHTML" hx-indicator="#flock-save-loading">
42
42
  <label for="save_filename">Save Flock As:</label>
43
43
  <input type="text" id="save_filename" name="save_filename"
44
44
  value="{{ current_filename if current_filename else (flock.name.replace(' ', '_').lower() + '.flock.yaml' if flock and flock.name else 'my_flock.flock.yaml') }}"
@@ -10,24 +10,28 @@
10
10
  </header>
11
11
 
12
12
  <div x-show="viewMode === 'json'">
13
- {% if result_data is string %}
14
- <p class="error" style="white-space: pre-wrap;">{{ result_data }}</p>
15
- {% elif result_data %}
16
- <pre><code style="word-break: break-all; white-space: pre-wrap;">{{ result_data | tojson(indent=2) }}</code></pre>
13
+ {# Check for the new result_raw_json variable first #}
14
+ {% if result_raw_json is defined %}
15
+ <pre><code class="language-json" style="word-break: break-all; white-space: pre-wrap;">{{ result_raw_json }}</code></pre>
16
+ {# Fallback for old context or if result was an error string from backend before formatting #}
17
+ {% elif result is string %}
18
+ <pre><code class="language-plaintext" style="word-break: break-all; white-space: pre-wrap;">{{ result }}</code></pre>
19
+ {% elif result %}
20
+ {# Fallback if result_raw_json is somehow not provided but result (dict) is #}
21
+ <pre><code class="language-json" style="word-break: break-all; white-space: pre-wrap;">{{ result | tojson(indent=2) }}</code></pre>
17
22
  {% else %}
18
23
  <p>No results to display yet.</p>
19
24
  {% endif %}
20
25
  </div>
21
26
 
22
27
  <div x-show="viewMode === 'structured'">
23
- {% if result_data is string %}
24
- <p class="error" style="white-space: pre-wrap;">{{ result_data }}</p>
25
- {% elif result_data is mapping %}
26
- {# Call our new macro for structured display #}
27
- {{ render_value(result_data) }}
28
- {% elif result_data %}
28
+ {% if result is string %}
29
+ <p class="error" style="white-space: pre-wrap;">{{ result }}</p>
30
+ {% elif result is mapping %}
31
+ {{ render_value(result) }}
32
+ {% elif result %}
29
33
  <p>Structured view not available for this result type (not a dictionary).</p>
30
- <pre><code>{{ result_data | tojson(indent=2) }}</code></pre>
34
+ <pre><code class="language-json" style="word-break: break-all; white-space: pre-wrap;">{{ result | tojson(indent=2) }}</code></pre>
31
35
  {% else %}
32
36
  <p>No results to display yet.</p>
33
37
  {% endif %}
@@ -31,8 +31,8 @@
31
31
  {% elif value is none %}
32
32
  <em style="color: var(--pico-code-color);">None</em>
33
33
  {% else %}
34
- {# Apply pre-wrap for multi-line strings #}
35
- <span style="white-space: pre-wrap; word-break: break-word;">{{ value }}</span>
34
+ {# Apply pre-wrap for multi-line strings and render markdown #}
35
+ <div class="markdown-content" style="word-break: break-word;">{{ value | markdown | safe }}</div>
36
36
  {% endif %}
37
37
  {% endmacro %}
38
38
 
@@ -14,6 +14,8 @@
14
14
  <link rel="stylesheet" href="/static/css/chat.css">
15
15
  <!-- Font Awesome for icons -->
16
16
  <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.1/css/all.min.css">
17
+ <!-- Prism.js CSS for syntax highlighting (okaidia theme) -->
18
+ <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/prism/1.29.0/themes/prism-okaidia.min.css" referrerpolicy="no-referrer" />
17
19
  {# Inline generated theme CSS variables #}
18
20
  {% if theme_css %}
19
21
  <style>
@@ -112,5 +114,30 @@
112
114
  <small>Built with FastAPI, HTMX, Pico.CSS by 🤍 white duck 🦆 - Theme: {{ active_theme_name | default('default') }}</small>
113
115
  </footer>
114
116
  </main>
117
+
118
+ <!-- Prism.js JS (core and autoloader) -->
119
+ <script src="https://cdnjs.cloudflare.com/ajax/libs/prism/1.29.0/components/prism-core.min.js" referrerpolicy="no-referrer"></script>
120
+ <script src="https://cdnjs.cloudflare.com/ajax/libs/prism/1.29.0/plugins/autoloader/prism-autoloader.min.js" referrerpolicy="no-referrer"></script>
121
+ <script>
122
+ // Add HTMX event listener for Prism highlighting
123
+ document.addEventListener('htmx:afterSwap', function(event) {
124
+ const resultsDisplay = document.getElementById('results-display');
125
+ // Check if the swapped element is the results display or a child of it
126
+ if (resultsDisplay && (event.detail.target === resultsDisplay || resultsDisplay.contains(event.detail.target))) {
127
+ if (typeof Prism !== 'undefined') {
128
+ // console.log('Prism highlighting triggered for swapped content in results-display.');
129
+ Prism.highlightAllUnder(resultsDisplay);
130
+ }
131
+ }
132
+ });
133
+
134
+ // Initial highlight on page load
135
+ document.addEventListener('DOMContentLoaded', () => {
136
+ if (typeof Prism !== 'undefined') {
137
+ // console.log('Prism initial highlighting on shared page.');
138
+ Prism.highlightAll();
139
+ }
140
+ });
141
+ </script>
115
142
  </body>
116
143
  </html>
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: flock-core
3
- Version: 0.4.0b49
3
+ Version: 0.4.0b50
4
4
  Summary: Declarative LLM Orchestration at Scale
5
5
  Author-email: Andre Ratzenberger <andre.ratzenberger@whiteduck.de>
6
6
  License-File: LICENSE
@@ -458,16 +458,16 @@ flock/tools/zendesk_tools.py,sha256=HQ7qBVSrRfemwolz0IOXl8Z02vJCLE6mTd-cARVdX88,
458
458
  flock/webapp/__init__.py,sha256=YtRbbyciN3Z2oMB9fdXZuvM3e49R8m2mY5qHLDoapRA,37
459
459
  flock/webapp/run.py,sha256=Ekg-mQSl7RUDJAEDTBJMIlLyvhWqWPMjg8hPqmgFREE,8945
460
460
  flock/webapp/app/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
461
- flock/webapp/app/chat.py,sha256=AcVwgq4SQyOQnx0rheJVuR0Pp8u6Dc15YH2aMfIdK2Q,25943
462
- flock/webapp/app/config.py,sha256=RVMvgOKRKKzE0T95UVai75iDXajTzV6mlPUhnW3Wloo,4812
461
+ flock/webapp/app/chat.py,sha256=NKSsrozVvnvxrLBtJjN4Ps_DMol66nw1eD5E8GmcOLU,26077
462
+ flock/webapp/app/config.py,sha256=lqmneujnNZk-EFJV5cWpvxkqisxH3T3zT_YOI0JYThE,4809
463
463
  flock/webapp/app/dependencies.py,sha256=JUcwY1N6SZplU141lMN2wk9dOC9er5HCedrKTJN9wJk,5533
464
- flock/webapp/app/main.py,sha256=pVxu2w4h6QNKzi6AO-k_aHjhOS6lPYwCY0IdGIIPqy0,53784
464
+ flock/webapp/app/main.py,sha256=489cZ_N8ZACRSGjY2PQomXM7bKYZL1_6s4BLRl4XSkM,53828
465
465
  flock/webapp/app/models_ui.py,sha256=vrEBLbhEp6FziAgBSFOLT1M7ckwadsTdT7qus5_NduE,329
466
466
  flock/webapp/app/theme_mapper.py,sha256=QzWwLWpED78oYp3FjZ9zxv1KxCyj43m8MZ0fhfzz37w,34302
467
467
  flock/webapp/app/utils.py,sha256=RF8DMKKAj1XPmm4txUdo2OdswI1ATQ7cqUm6G9JFDzA,2942
468
468
  flock/webapp/app/api/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
469
469
  flock/webapp/app/api/agent_management.py,sha256=5xqO94QjjAYvxImyjKV9EGUQOvo4n3eqs7pGwGPSQJ4,10394
470
- flock/webapp/app/api/execution.py,sha256=DO2dljCXa4zwedRbtjU_QiCTP-KRVSbFknUKpVcHBuk,13013
470
+ flock/webapp/app/api/execution.py,sha256=NNNG_ZqYS80WoLMD7MSCyDhqkkvCVMb_MfIm3dOs_HA,10381
471
471
  flock/webapp/app/api/flock_management.py,sha256=1o-6-36kTnUjI3am_BqLpdrcz0aqFXrxE-hQHIFcCsg,4869
472
472
  flock/webapp/app/api/registry_viewer.py,sha256=IoInxJiRR0yFlecG_l2_eRc6l35RQQyEDMG9BcBkipY,1020
473
473
  flock/webapp/app/services/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -480,14 +480,14 @@ flock/webapp/static/css/components.css,sha256=WnicEHy3ptPzggKmyG9_oZp3X30EMJBUW3
480
480
  flock/webapp/static/css/header.css,sha256=E9MgItZCk34S65NfMJ001ZsRz4oyFSJex8KvINMtCn0,1043
481
481
  flock/webapp/static/css/layout.css,sha256=ocDd7dmezdQzNAQDuQSv1xZ8-pcbNgYLUYJB1SKcfvw,1526
482
482
  flock/webapp/static/css/sidebar.css,sha256=gCwLTAiIvmHGksm0rHDpMsOGCDKBMxqx_aEc8ZQcQF8,3066
483
- flock/webapp/templates/base.html,sha256=013TyI0TvzyvjnIhEr3ZgJYSAIVQK2ayPAngdi0hF18,4937
484
- flock/webapp/templates/chat.html,sha256=CieTTl1RWG0uyltrBthblPBzNDx061WUE1x79UxT2Og,4294
483
+ flock/webapp/templates/base.html,sha256=Eqp-WYI8ZaYr8CiKzfquYLaoWtKJ7vtHHCJBS4b53Tw,9757
484
+ flock/webapp/templates/chat.html,sha256=4g5qgKGmkvFwuTcuf57Q2CSHj2i0MW98PbUZXaaN74I,7303
485
485
  flock/webapp/templates/chat_settings.html,sha256=nYz6ihYAUA9zN-Jru565QNl8_eJdoLMWC2LdZJtZ-20,862
486
486
  flock/webapp/templates/flock_editor.html,sha256=ysDExf9zMj4SMsSXZUpCtG9EjIv8VJ5xL4IJQOMlb7o,542
487
487
  flock/webapp/templates/index.html,sha256=eK7s5Cnh63unqPwq9NGZGEKyvYwkhudfmSn9su3Ctyg,412
488
488
  flock/webapp/templates/registry_viewer.html,sha256=suAiWDvBxJ8SsF9MhheuN6MMQUZuIhTlurmbFOcYJfI,3235
489
- flock/webapp/templates/shared_run_page.html,sha256=uB04jvhGISgpXl-zTJ1lbFTze9mQQXFmkYSZcx43PUc,6429
490
- flock/webapp/templates/partials/_agent_detail_form.html,sha256=oLz17lmv8s-DI9lOxODLJpc57NRUPmnLlOqxyDFYTDE,6015
489
+ flock/webapp/templates/shared_run_page.html,sha256=VaiCieI1kXP6y1eFprbVh9tG1-5CS-d-z7Kw2cUAeis,7985
490
+ flock/webapp/templates/partials/_agent_detail_form.html,sha256=a-YM1CozCXBRoBEdfAw3tL9X-rjRy4OWeiwxk6Dcjfg,6024
491
491
  flock/webapp/templates/partials/_agent_list.html,sha256=comYjOeUxQvlJzS-3D4OruJKlhC3uhCgo-X-nqiOhkA,1037
492
492
  flock/webapp/templates/partials/_agent_manager_view.html,sha256=oUJ-t2Mk3o4xjQ_HtHz0glgaHM8eqZpPB4i24ToJiJ8,2565
493
493
  flock/webapp/templates/partials/_agent_tools_checklist.html,sha256=T60fb7OrJYHUw0hJLC_otskgvbH9dZXbv5klgWBkSWk,686
@@ -504,20 +504,20 @@ flock/webapp/templates/partials/_env_vars_table.html,sha256=6TFUWvkYwzwodqXZ0yJh
504
504
  flock/webapp/templates/partials/_execution_form.html,sha256=296AFx0WSbCzX8t-L1pRl8s0AUzeOb2fmTiRlcwYoIg,3274
505
505
  flock/webapp/templates/partials/_execution_view_container.html,sha256=XuphmZKYf2IYSeA9XHqtnwAntBylrFASDXVlLBJUeDk,1031
506
506
  flock/webapp/templates/partials/_flock_file_list.html,sha256=FjIxAqB0OxA0mQ8f2jBX1_M_AM5ea7gCA8PEjPpiZVc,1209
507
- flock/webapp/templates/partials/_flock_properties_form.html,sha256=0xNK_h5LrZrGCFyKfOLsvEaIpK2LlDfCte8bl0-AwdI,2885
507
+ flock/webapp/templates/partials/_flock_properties_form.html,sha256=alOsGYzktVX6aYtfxRHganBfipkzx5Kk4RxF6C0IHhk,2891
508
508
  flock/webapp/templates/partials/_flock_upload_form.html,sha256=h2dIPwPeTg5dv_ubrZiwBXReF0NjzJ6eKSwwz7mbQQs,960
509
509
  flock/webapp/templates/partials/_header_flock_status.html,sha256=reNB4Prsu9lObz5tFhGk3AMe4bNw92gDJZUKABVaVBM,158
510
510
  flock/webapp/templates/partials/_load_manager_view.html,sha256=2u4lufQMEpUlQOThUzo1zrE3AulDQ-aErruS6t91W44,2909
511
511
  flock/webapp/templates/partials/_registry_table.html,sha256=z4EW5G3DTknymBeSlpL2PZLcb2143P35upMnmHFfeJs,715
512
512
  flock/webapp/templates/partials/_registry_viewer_content.html,sha256=iQyxaLUzz1IcZouRLcMg73k-xcOZvOHVPfpuU7uXgYo,1891
513
- flock/webapp/templates/partials/_results_display.html,sha256=vuAbIdnG_7jzeHxeeoRvPqStD_7CJwXnyhvry_kMfLQ,1625
513
+ flock/webapp/templates/partials/_results_display.html,sha256=zwWF7uhYfOSsPWDdG9A11ccBBgu-Pz6cupvJ1f4xTB0,2103
514
514
  flock/webapp/templates/partials/_settings_env_content.html,sha256=Q1Xr6wLHLlqiduqNk6PyF1B4juP-vvqLOLZyiHHNRLc,572
515
515
  flock/webapp/templates/partials/_settings_theme_content.html,sha256=-y5vGRKBZf3Cp5DDE1M4Qw-yunuMtCG54Sa7r60XfJE,807
516
516
  flock/webapp/templates/partials/_settings_view.html,sha256=7Uy2EfAgVJ2Kac5S6nkeaIEr2tSagVyR5CBbf07fbSQ,1349
517
517
  flock/webapp/templates/partials/_share_chat_link_snippet.html,sha256=N83lNAbkZiDfzZYviKwURPGGErSZhRlxnNzUqXsB7lE,793
518
518
  flock/webapp/templates/partials/_share_link_snippet.html,sha256=6en9lOdtu8FwVbtmkJzSQpHQ1WFXHnCbe84FDgAEF3U,1533
519
519
  flock/webapp/templates/partials/_sidebar.html,sha256=uA-SZKfVpxImT8Acpw2hhpJbOk1BlaLeSzRjleYfuSE,4450
520
- flock/webapp/templates/partials/_structured_data_view.html,sha256=IsmGbm2rKHZr6qx0a_n6QGs89Rq4xNFhymrZVI6OShc,2063
520
+ flock/webapp/templates/partials/_structured_data_view.html,sha256=TEaXcMGba9ruxEc_MLxygIO1qWcuSTo1FnosFtGSKWI,2101
521
521
  flock/webapp/templates/partials/_theme_preview.html,sha256=81vP5z8958LjhGWGwjVAVw3zW0uvYwfcXlU30i9exmo,867
522
522
  flock/workflow/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
523
523
  flock/workflow/activities.py,sha256=fyvefDOWZhhj5gCYIHR9Aqm2DbE6XI6-sXESFnnYRuc,9911
@@ -526,8 +526,8 @@ flock/workflow/agent_execution_activity.py,sha256=Gy6FtuVAjf0NiUXmC3syS2eJpNQF4R
526
526
  flock/workflow/flock_workflow.py,sha256=iSUF_soFvWar0ffpkzE4irkDZRx0p4HnwmEBi_Ne2sY,9666
527
527
  flock/workflow/temporal_config.py,sha256=3_8O7SDEjMsSMXsWJBfnb6XTp0TFaz39uyzSlMTSF_I,3988
528
528
  flock/workflow/temporal_setup.py,sha256=YIHnSBntzOchHfMSh8hoLeNXrz3B1UbR14YrR6soM7A,1606
529
- flock_core-0.4.0b49.dist-info/METADATA,sha256=BV-rirx2H3Z43076Y0lQjFUSaRQ9WxlAsmN9FJzy_-8,17879
530
- flock_core-0.4.0b49.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
531
- flock_core-0.4.0b49.dist-info/entry_points.txt,sha256=rWaS5KSpkTmWySURGFZk6PhbJ87TmvcFQDi2uzjlagQ,37
532
- flock_core-0.4.0b49.dist-info/licenses/LICENSE,sha256=iYEqWy0wjULzM9GAERaybP4LBiPeu7Z1NEliLUdJKSc,1072
533
- flock_core-0.4.0b49.dist-info/RECORD,,
529
+ flock_core-0.4.0b50.dist-info/METADATA,sha256=iqhiWpNagA97dhguRWqDQOhMmlb3-PGKFYT-v0LY_aU,17879
530
+ flock_core-0.4.0b50.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
531
+ flock_core-0.4.0b50.dist-info/entry_points.txt,sha256=rWaS5KSpkTmWySURGFZk6PhbJ87TmvcFQDi2uzjlagQ,37
532
+ flock_core-0.4.0b50.dist-info/licenses/LICENSE,sha256=iYEqWy0wjULzM9GAERaybP4LBiPeu7Z1NEliLUdJKSc,1072
533
+ flock_core-0.4.0b50.dist-info/RECORD,,