flock-core 0.4.0b33__py3-none-any.whl → 0.4.0b35__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 +27 -5
- flock/core/api/main.py +138 -39
- flock/core/util/spliter.py +139 -54
- 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 +9 -0
- flock/webapp/app/main.py +571 -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/utils.py +85 -0
- flock/webapp/run.py +30 -0
- flock/webapp/static/css/custom.css +527 -0
- flock/webapp/templates/base.html +98 -0
- flock/webapp/templates/flock_editor.html +17 -0
- flock/webapp/templates/index.html +12 -0
- flock/webapp/templates/partials/_agent_detail_form.html +97 -0
- flock/webapp/templates/partials/_agent_list.html +24 -0
- flock/webapp/templates/partials/_agent_manager_view.html +15 -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/_execution_form.html +48 -0
- flock/webapp/templates/partials/_execution_view_container.html +19 -0
- flock/webapp/templates/partials/_flock_file_list.html +24 -0
- flock/webapp/templates/partials/_flock_properties_form.html +51 -0
- flock/webapp/templates/partials/_flock_upload_form.html +17 -0
- flock/webapp/templates/partials/_load_manage_view.html +88 -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/_sidebar.html +63 -0
- flock/webapp/templates/partials/_structured_data_view.html +40 -0
- flock/webapp/templates/registry_viewer.html +84 -0
- {flock_core-0.4.0b33.dist-info → flock_core-0.4.0b35.dist-info}/METADATA +1 -1
- {flock_core-0.4.0b33.dist-info → flock_core-0.4.0b35.dist-info}/RECORD +48 -8
- {flock_core-0.4.0b33.dist-info → flock_core-0.4.0b35.dist-info}/WHEEL +0 -0
- {flock_core-0.4.0b33.dist-info → flock_core-0.4.0b35.dist-info}/entry_points.txt +0 -0
- {flock_core-0.4.0b33.dist-info → flock_core-0.4.0b35.dist-info}/licenses/LICENSE +0 -0
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
<article id="agent-detail-form-content">
|
|
2
|
+
<header>
|
|
3
|
+
<h4>{% if is_new %}Add New Agent{% else %}Edit Agent: {{ agent.name if agent else '' }}{% endif %}</h4>
|
|
4
|
+
</header>
|
|
5
|
+
{% if form_message %}
|
|
6
|
+
<div class="form-message {{ 'success' if success else 'error' }}"
|
|
7
|
+
x-data="{ show: true }" x-show="show" x-init="setTimeout(() => show = false, 3000)"
|
|
8
|
+
x-transition:leave="transition ease-in duration-300"
|
|
9
|
+
x-transition:leave-start="opacity-100"
|
|
10
|
+
x-transition:leave-end="opacity-0">
|
|
11
|
+
{{ form_message }}
|
|
12
|
+
</div>
|
|
13
|
+
{% endif %}
|
|
14
|
+
|
|
15
|
+
<form {% if is_new %}
|
|
16
|
+
hx-post="/api/flocks/htmx/agents"
|
|
17
|
+
{% else %}
|
|
18
|
+
hx-put="/api/flocks/htmx/agents/{{ agent.name if agent else '' }}"
|
|
19
|
+
{% endif %}
|
|
20
|
+
hx-target="#agent-detail-form-content"
|
|
21
|
+
hx-swap="innerHTML"
|
|
22
|
+
hx-indicator="#agent-detail-loading-indicator">
|
|
23
|
+
|
|
24
|
+
<fieldset>
|
|
25
|
+
<label for="agent_name_field">Name *</label>
|
|
26
|
+
<input type="text" id="agent_name_field" name="agent_name" value="{{ agent.name if agent and not form_errors else (form_data.agent_name if form_data else '') }}" required placeholder="my_processing_agent">
|
|
27
|
+
{% if form_errors and form_errors.agent_name %}<small class="field-error">{{ form_errors.agent_name }}</small>{% endif %}
|
|
28
|
+
|
|
29
|
+
<label for="agent_description_field">Description</label>
|
|
30
|
+
<textarea id="agent_description_field" name="agent_description" placeholder="Briefly describe what this agent does.">{{ agent.description if agent and not form_errors else (form_data.agent_description if form_data else '') }}</textarea>
|
|
31
|
+
|
|
32
|
+
<label for="agent_model_field">Model Override (Optional)</label>
|
|
33
|
+
<input type="text" id="agent_model_field" name="agent_model" value="{{ agent.model if agent and agent.model and not form_errors else (form_data.agent_model if form_data else '') }}" placeholder="e.g., openai/gpt-3.5-turbo (uses Flock default if blank)">
|
|
34
|
+
|
|
35
|
+
<label for="input_signature_field">Input Signature *</label>
|
|
36
|
+
<input type="text" id="input_signature_field" name="input_signature" value="{{ agent.input if agent and not form_errors else (form_data.input_signature if form_data else '') }}" required placeholder="e.g., query: str | The user's question, context: list[str]">
|
|
37
|
+
<small>Format: `name1: type1 | desc1, name2: type2 | desc2`</small>
|
|
38
|
+
{% if form_errors and form_errors.input_signature %}<small class="field-error">{{ form_errors.input_signature }}</small>{% endif %}
|
|
39
|
+
|
|
40
|
+
<label for="output_signature_field">Output Signature *</label>
|
|
41
|
+
<input type="text" id="output_signature_field" name="output_signature" value="{{ agent.output if agent and not form_errors else (form_data.output_signature if form_data else '') }}" required placeholder="e.g., answer: str | The final answer, sources: list[str]">
|
|
42
|
+
<small>Format: `name1: type1 | desc1, name2: type2 | desc2`</small>
|
|
43
|
+
{% if form_errors and form_errors.output_signature %}<small class="field-error">{{ form_errors.output_signature }}</small>{% endif %}
|
|
44
|
+
</fieldset>
|
|
45
|
+
|
|
46
|
+
<fieldset>
|
|
47
|
+
<legend>Tools (Optional)</legend>
|
|
48
|
+
<div class="tool-checklist">
|
|
49
|
+
{% if registered_tools %}
|
|
50
|
+
{% for tool in registered_tools %}
|
|
51
|
+
<label for="tool_{{ tool.name }}">
|
|
52
|
+
<input type="checkbox" id="tool_{{ tool.name }}" name="tools" value="{{ tool.name }}"
|
|
53
|
+
{% if tool.name in (current_tools if not form_errors else (form_data.getlist('tools') if form_data else [])) %}checked{% endif %}>
|
|
54
|
+
{{ tool.name }} <small>({{ tool.module }})</small>
|
|
55
|
+
</label>
|
|
56
|
+
{% endfor %}
|
|
57
|
+
{% else %}
|
|
58
|
+
<p>No tools registered. Add tools via the Registry page or ensure they are discovered by Flock.</p>
|
|
59
|
+
{% endif %}
|
|
60
|
+
</div>
|
|
61
|
+
</fieldset>
|
|
62
|
+
|
|
63
|
+
<fieldset>
|
|
64
|
+
<legend>Routing (Default Handoff)</legend>
|
|
65
|
+
<label for="default_router_handoff_field">Next Agent Name (Optional)</label>
|
|
66
|
+
<input type="text" id="default_router_handoff_field" name="default_router_handoff"
|
|
67
|
+
value="{{ agent.handoff_router.config.hand_off if agent and agent.handoff_router and agent.handoff_router.config and agent.handoff_router.config.hand_off is string and not form_errors else (form_data.default_router_handoff if form_data else '') }}"
|
|
68
|
+
placeholder="Enter name of next agent">
|
|
69
|
+
<small>If set, this agent will hand off to the specified agent by default.</small>
|
|
70
|
+
</fieldset>
|
|
71
|
+
|
|
72
|
+
<div class="grid">
|
|
73
|
+
<button type="submit">
|
|
74
|
+
{% if is_new %}Create Agent{% else %}Save Changes{% endif %}
|
|
75
|
+
</button>
|
|
76
|
+
{% if not is_new and agent %}
|
|
77
|
+
<button type="button" role="button" class="secondary outline"
|
|
78
|
+
hx-delete="/api/flocks/htmx/agents/{{ agent.name }}"
|
|
79
|
+
hx-target="#agent-detail-form-content"
|
|
80
|
+
hx-confirm="Are you sure you want to delete agent '{{ agent.name }}'?"
|
|
81
|
+
hx-indicator="#agent-detail-loading-indicator">
|
|
82
|
+
Delete Agent
|
|
83
|
+
</button>
|
|
84
|
+
{% endif %}
|
|
85
|
+
<button type="button" class="outline"
|
|
86
|
+
hx-get="/api/flocks/htmx/agents/new-agent-form"
|
|
87
|
+
hx-target="#agent-detail-panel"
|
|
88
|
+
hx-swap="innerHTML"
|
|
89
|
+
hx-indicator="#agent-detail-loading-indicator">
|
|
90
|
+
Cancel / New Form
|
|
91
|
+
</button>
|
|
92
|
+
</div>
|
|
93
|
+
<div id="agent-detail-loading-indicator" class="htmx-indicator" style="margin-top: 0.5rem;">
|
|
94
|
+
<progress indeterminate></progress> Processing...
|
|
95
|
+
</div>
|
|
96
|
+
</form>
|
|
97
|
+
</article>
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
<article id="agent-list-content">
|
|
2
|
+
<header class="grid">
|
|
3
|
+
<h4>Agents ({{ flock.agents|length }})</h4>
|
|
4
|
+
<div style="text-align: right;">
|
|
5
|
+
<button role="button" class="outline" hx-get="/api/flocks/htmx/agents/new-agent-form" hx-target="#agent-detail-panel" hx-swap="innerHTML">Add New Agent</button>
|
|
6
|
+
</div>
|
|
7
|
+
</header>
|
|
8
|
+
{% if message %}
|
|
9
|
+
<div class="form-message {{ 'success' if success else 'error' }}">{{ message }}</div>
|
|
10
|
+
{% endif %}
|
|
11
|
+
{% if flock.agents %}
|
|
12
|
+
<ul>
|
|
13
|
+
{% for agent_name, agent in flock.agents.items() %}
|
|
14
|
+
<li hx-get="/api/flocks/htmx/agents/{{ agent.name }}/details-form" hx-target="#agent-detail-panel" hx-swap="innerHTML" hx-indicator="#agent-detail-loading">
|
|
15
|
+
<strong>{{ agent.name }}</strong><br>
|
|
16
|
+
<small>{{ agent.description|truncate(80) if agent.description else 'No description' }}</small>
|
|
17
|
+
</li>
|
|
18
|
+
{% endfor %}
|
|
19
|
+
</ul>
|
|
20
|
+
{% else %}
|
|
21
|
+
<p>No agents defined in this Flock yet. Click "Add New Agent" to create one.</p>
|
|
22
|
+
{% endif %}
|
|
23
|
+
<div id="agent-list-loading" class="htmx-indicator">Loading agents... <progress></progress></div>
|
|
24
|
+
</article>
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
<div class="editor-grid"> {# Use the improved two-column grid #}
|
|
2
|
+
<section id="agent-list-panel"
|
|
3
|
+
hx-get="/api/flocks/htmx/agent-list"
|
|
4
|
+
hx-trigger="load, agentListChanged from:body" {# Reload when agent list changes #}
|
|
5
|
+
hx-swap="innerHTML">
|
|
6
|
+
<article><p>Loading agents...</p><progress></progress></article>
|
|
7
|
+
</section>
|
|
8
|
+
|
|
9
|
+
<section id="agent-detail-panel">
|
|
10
|
+
<article>
|
|
11
|
+
<header><h4>Agent Details</h4></header>
|
|
12
|
+
<p>Select an agent from the list to view/edit, or click "Add New Agent".</p>
|
|
13
|
+
</article>
|
|
14
|
+
</section>
|
|
15
|
+
</div>
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
<!-- This partial might be used if tool selection becomes more complex -->
|
|
2
|
+
<!-- For MVP, it's integrated into _agent_detail_form.html -->
|
|
3
|
+
<fieldset>
|
|
4
|
+
<legend>Select Tools</legend>
|
|
5
|
+
{% for tool in registered_tools %}
|
|
6
|
+
<label for="tool_{{ tool.name }}_{{ context_id }}"> <!-- context_id for uniqueness if form is loaded multiple times -->
|
|
7
|
+
<input type="checkbox" id="tool_{{ tool.name }}_{{ context_id }}" name="tools" value="{{ tool.name }}"
|
|
8
|
+
{% if tool.name in current_tools %}checked{% endif %}>
|
|
9
|
+
{{ tool.name }} <small>({{ tool.module }})</small>
|
|
10
|
+
</label>
|
|
11
|
+
{% else %}
|
|
12
|
+
<p>No tools available in registry.</p>
|
|
13
|
+
{% endfor %}
|
|
14
|
+
</fieldset>
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
<article id="create-flock-view-content">
|
|
2
|
+
<header>
|
|
3
|
+
<h3>Create or Upload Flock</h3>
|
|
4
|
+
</header>
|
|
5
|
+
|
|
6
|
+
{% if error_message %}
|
|
7
|
+
<div class="error DANGER" role="alert" x-data="{ show: true }" x-show="show" x-init="setTimeout(() => show = false, 5000)">
|
|
8
|
+
{{ error_message }} <button type="button" class="close" @click="show = false">×</button>
|
|
9
|
+
</div>
|
|
10
|
+
{% endif %}
|
|
11
|
+
{% if success_message %} {# For messages after an action within this view #}
|
|
12
|
+
<div class="success SUCCESS" role="alert" x-data="{ show: true }" x-show="show" x-init="setTimeout(() => show = false, 5000)">
|
|
13
|
+
{{ success_message }} <button type="button" class="close" @click="show = false">×</button>
|
|
14
|
+
</div>
|
|
15
|
+
{% endif %}
|
|
16
|
+
|
|
17
|
+
<section id="create-by-details-section">
|
|
18
|
+
<h4>Define New Flock Properties</h4>
|
|
19
|
+
<form hx-post="/ui/create-flock"
|
|
20
|
+
hx-target="#main-content-area" {# On success, loads properties form into main area #}
|
|
21
|
+
hx-swap="innerHTML"
|
|
22
|
+
hx-indicator="#create-indicator-details">
|
|
23
|
+
<label for="flock_name_create_details">Flock Name *</label>
|
|
24
|
+
<input type="text" id="flock_name_create_details" name="flock_name" placeholder="My Awesome Flock" required>
|
|
25
|
+
|
|
26
|
+
<label for="default_model_create_details">Default Model (Optional)</label>
|
|
27
|
+
<input type="text" id="default_model_create_details" name="default_model" placeholder="openai/gpt-4o">
|
|
28
|
+
|
|
29
|
+
<label for="description_create_details">Description (Optional)</label>
|
|
30
|
+
<textarea id="description_create_details" name="description" placeholder="A brief description..."></textarea>
|
|
31
|
+
|
|
32
|
+
<button type="submit">Create and Edit Flock</button>
|
|
33
|
+
<span id="create-indicator-details" class="htmx-indicator"><progress indeterminate></progress> Creating...</span>
|
|
34
|
+
</form>
|
|
35
|
+
</section>
|
|
36
|
+
|
|
37
|
+
<hr>
|
|
38
|
+
|
|
39
|
+
<section id="create-by-upload-section">
|
|
40
|
+
<h4>Upload Existing Flock File</h4>
|
|
41
|
+
<form hx-post="/ui/load-flock-action/by-upload"
|
|
42
|
+
hx-target="#main-content-area" {# On success, loads properties form into main area #}
|
|
43
|
+
hx-swap="innerHTML"
|
|
44
|
+
hx-encoding="multipart/form-data"
|
|
45
|
+
hx-indicator="#create-upload-loading-indicator">
|
|
46
|
+
<label for="flock_file_upload_create">Upload <code>.flock.yaml</code>, <code>.yaml</code>, or <code>.yml</code> file:</label>
|
|
47
|
+
<input type="file" id="flock_file_upload_create" name="flock_file_upload" accept=".yaml,.yml,.flock" required>
|
|
48
|
+
<button type="submit">Upload and Edit Flock</button>
|
|
49
|
+
<span id="create-upload-loading-indicator" class="htmx-indicator"><progress indeterminate></progress> Uploading...</span>
|
|
50
|
+
</form>
|
|
51
|
+
</section>
|
|
52
|
+
</article>
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
<article>
|
|
2
|
+
<header>
|
|
3
|
+
<h5>Flock File: <code>{{ selected_filename }}</code></h5>
|
|
4
|
+
</header>
|
|
5
|
+
<p>Details for this Flock file (e.g., size, last modified) could be shown here if fetched.</p>
|
|
6
|
+
<form hx-post="/ui/load-flock-action/by-name"
|
|
7
|
+
hx-target="#main-content-area" {# Target the main area to show editor on success #}
|
|
8
|
+
hx-swap="innerHTML"
|
|
9
|
+
hx-indicator="#dashboard-flock-detail-loading-indicator">
|
|
10
|
+
<input type="hidden" name="selected_flock_filename" value="{{ selected_filename }}">
|
|
11
|
+
<button type="submit">Load this Flock into Editor</button>
|
|
12
|
+
<span id="dashboard-flock-detail-loading-indicator" class="htmx-indicator"><progress indeterminate></progress></span>
|
|
13
|
+
</form>
|
|
14
|
+
<hr>
|
|
15
|
+
<p><small>Or, you can use the form below to upload a different Flock file.</small></p>
|
|
16
|
+
{# Include the upload form again or link back to it #}
|
|
17
|
+
<div hx-get="/ui/htmx/dashboard-upload-flock-form" hx-trigger="load" hx-swap="innerHTML"></div>
|
|
18
|
+
</article>
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
{% if flock_files %}
|
|
2
|
+
<ul class="item-list">
|
|
3
|
+
{% for file_name in flock_files %}
|
|
4
|
+
<li hx-get="/ui/htmx/dashboard-flock-properties-preview/{{ file_name }}"
|
|
5
|
+
hx-target="#flock-properties-or-action-content" {# Target the right pane #}
|
|
6
|
+
hx-swap="innerHTML"
|
|
7
|
+
hx-indicator="#flock-properties-or-action-content progress"
|
|
8
|
+
{# Optional: Add hx-select-from-response or other advanced HTMX if needed to highlight this li #}
|
|
9
|
+
onclick="this.closest('ul').querySelectorAll('li').forEach(li => li.classList.remove('selected-item')); this.classList.add('selected-item');"
|
|
10
|
+
>
|
|
11
|
+
<strong>{{ file_name }}</strong>
|
|
12
|
+
</li>
|
|
13
|
+
{% endfor %}
|
|
14
|
+
</ul>
|
|
15
|
+
{% else %}
|
|
16
|
+
<p style="padding: 1rem;">No Flock files found in <code>./.flock_ui_projects/</code>.</p>
|
|
17
|
+
{% endif %}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
<article id="flock-preview-article">
|
|
2
|
+
<header>
|
|
3
|
+
<h4>Preview: {{ preview_flock.name if preview_flock else selected_filename }}</h4>
|
|
4
|
+
</header>
|
|
5
|
+
{% if preview_flock %}
|
|
6
|
+
<p><strong>Default Model:</strong> {{ preview_flock.model or 'Not set' }}</p>
|
|
7
|
+
<p><strong>Description:</strong> {{ preview_flock.description or 'None' }}</p>
|
|
8
|
+
<p><strong>Agents:</strong> {{ preview_flock.agents|length }}</p>
|
|
9
|
+
|
|
10
|
+
<form hx-post="/ui/load-flock-action/by-name"
|
|
11
|
+
hx-target="#main-content-area" {# This will load the full editor for this flock #}
|
|
12
|
+
hx-swap="innerHTML"
|
|
13
|
+
hx-indicator="#flock-preview-loading-indicator">
|
|
14
|
+
<input type="hidden" name="selected_flock_filename" value="{{ selected_filename }}">
|
|
15
|
+
<button type="submit" class="primary">Load this Flock into Editor</button>
|
|
16
|
+
<span id="flock-preview-loading-indicator" class="htmx-indicator"><progress indeterminate></progress></span>
|
|
17
|
+
</form>
|
|
18
|
+
{% else %}
|
|
19
|
+
<p class="error">Could not load preview for <code>{{ selected_filename }}</code>. It might be corrupted or not a valid Flock file.</p>
|
|
20
|
+
<p><small>You can still attempt to load it into the editor.</small></p>
|
|
21
|
+
<form hx-post="/ui/load-flock-action/by-name" hx-target="#main-content-area" hx-swap="innerHTML">
|
|
22
|
+
<input type="hidden" name="selected_flock_filename" value="{{ selected_filename }}">
|
|
23
|
+
<button type="submit" class="secondary">Attempt to Load into Editor</button>
|
|
24
|
+
</form>
|
|
25
|
+
{% endif %}
|
|
26
|
+
<hr>
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
</article>
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
<article>
|
|
2
|
+
<header>
|
|
3
|
+
<h5>Upload New Flock File</h5>
|
|
4
|
+
</header>
|
|
5
|
+
<form hx-post="/ui/load-flock-action/by-upload"
|
|
6
|
+
hx-target="#main-content-area" {# Target the main area to show editor on success #}
|
|
7
|
+
hx-swap="innerHTML"
|
|
8
|
+
hx-encoding="multipart/form-data"
|
|
9
|
+
hx-indicator="#dashboard-upload-loading-indicator">
|
|
10
|
+
<label for="flock_file_upload_dashboard">Upload <code>.flock.yaml</code>, <code>.yaml</code>, or <code>.yml</code> file:</label>
|
|
11
|
+
<input type="file" id="flock_file_upload_dashboard" name="flock_file_upload" accept=".yaml,.yml,.flock" required>
|
|
12
|
+
<button type="submit">Upload and Load Flock</button>
|
|
13
|
+
<span id="dashboard-upload-loading-indicator" class="htmx-indicator"><progress indeterminate></progress> Uploading...</span>
|
|
14
|
+
</form>
|
|
15
|
+
<hr>
|
|
16
|
+
<p><small>Alternatively, select a Flock from the list on the left to view its details or load it.</small></p>
|
|
17
|
+
</article>
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
{% if input_fields %}
|
|
2
|
+
{% for field in input_fields %}
|
|
3
|
+
<fieldset> {# Group each field #}
|
|
4
|
+
<label for="agent_input_{{ field.name }}">{{ field.name }} ({{ field.type }})</label>
|
|
5
|
+
{% if field.description %}
|
|
6
|
+
<small>{{ field.description }}</small>
|
|
7
|
+
{% endif %}
|
|
8
|
+
{% if field.html_type == 'textarea' %}
|
|
9
|
+
<textarea id="agent_input_{{ field.name }}" name="agent_input_{{ field.name }}" rows="3" placeholder="{{ field.placeholder if field.placeholder else ('Enter ' + field.type) }}"></textarea>
|
|
10
|
+
{% elif field.html_type == 'checkbox' %}
|
|
11
|
+
<label for="agent_input_{{ field.name }}_cb">
|
|
12
|
+
<input type="checkbox" id="agent_input_{{ field.name }}_cb" name="agent_input_{{ field.name }}" value="true">
|
|
13
|
+
Enabled
|
|
14
|
+
</label>
|
|
15
|
+
{% else %}
|
|
16
|
+
<input type="{{ field.html_type }}" id="agent_input_{{ field.name }}" name="agent_input_{{ field.name }}" placeholder="{{ field.placeholder if field.placeholder else ('Enter ' + field.type) }}">
|
|
17
|
+
{% endif %}
|
|
18
|
+
</fieldset>
|
|
19
|
+
{% endfor %}
|
|
20
|
+
{% else %}
|
|
21
|
+
<p><small>This agent requires no specific inputs, or input signature could not be parsed.</small></p>
|
|
22
|
+
{% endif %}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
<article id="execution-form-content">
|
|
2
|
+
<header>
|
|
3
|
+
<h4>Run Flock</h4>
|
|
4
|
+
</header>
|
|
5
|
+
{% if flock and flock.agents %}
|
|
6
|
+
<form hx-post="/api/flocks/htmx/run"
|
|
7
|
+
hx-target="#results-display"
|
|
8
|
+
hx-swap="innerHTML"
|
|
9
|
+
hx-indicator="#run-loading-indicator"
|
|
10
|
+
x-data="{ selectedAgentForInput: '' }">
|
|
11
|
+
|
|
12
|
+
<label for="start_agent_name_select">Select Start Agent:</label>
|
|
13
|
+
<select id="start_agent_name_select"
|
|
14
|
+
name="start_agent_name"
|
|
15
|
+
required
|
|
16
|
+
x-model="selectedAgentForInput"
|
|
17
|
+
@change="
|
|
18
|
+
if ($event.target.value) {
|
|
19
|
+
htmx.ajax('GET', '/api/flocks/htmx/agents/' + $event.target.value + '/input-form', {target: '#dynamic-input-form-fields', swap: 'innerHTML', indicator: '#input-form-loading-indicator'});
|
|
20
|
+
} else {
|
|
21
|
+
document.getElementById('dynamic-input-form-fields').innerHTML = '<p><small>Select an agent to see its input fields.</small></p>';
|
|
22
|
+
}
|
|
23
|
+
">
|
|
24
|
+
<option value="" disabled {% if not selected_agent_name %}selected{% endif %}>-- Choose an agent --</option>
|
|
25
|
+
{% for agent_name_key in flock.agents.keys() %}
|
|
26
|
+
<option value="{{ agent_name_key }}" {% if selected_agent_name == agent_name_key %}selected{% endif %}>{{ agent_name_key }}</option>
|
|
27
|
+
{% endfor %}
|
|
28
|
+
</select>
|
|
29
|
+
|
|
30
|
+
<div id="dynamic-input-form-fields">
|
|
31
|
+
<!-- Input fields for the selected agent will be loaded here -->
|
|
32
|
+
<p><small>Select an agent to see its input fields.</small></p>
|
|
33
|
+
</div>
|
|
34
|
+
<div id="input-form-loading-indicator" class="htmx-indicator">
|
|
35
|
+
<progress indeterminate></progress> Loading input form...
|
|
36
|
+
</div>
|
|
37
|
+
|
|
38
|
+
<button type="submit" {% if not flock.agents %}disabled{% endif %}>Run Flock</button>
|
|
39
|
+
<span id="run-loading-indicator" class="htmx-indicator">
|
|
40
|
+
<progress indeterminate></progress> Running...
|
|
41
|
+
</span>
|
|
42
|
+
</form>
|
|
43
|
+
{% elif flock and not flock.agents %}
|
|
44
|
+
<p>No agents available in the current Flock. Add agents to enable execution.</p>
|
|
45
|
+
{% else %}
|
|
46
|
+
<p>Load or create a Flock to enable execution.</p>
|
|
47
|
+
{% endif %}
|
|
48
|
+
</article>
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
<article id="execution-view-container-content">
|
|
2
|
+
{# The Execution Form will be loaded here #}
|
|
3
|
+
<div id="execution-form-wrapper"
|
|
4
|
+
hx-get="/api/flocks/htmx/execution-form-content" {# New endpoint for just the form #}
|
|
5
|
+
hx-trigger="load"
|
|
6
|
+
hx-swap="innerHTML">
|
|
7
|
+
<p>Loading execution form...</p><progress indeterminate></progress>
|
|
8
|
+
</div>
|
|
9
|
+
|
|
10
|
+
{# The Results Display area, always present when this container is loaded #}
|
|
11
|
+
<section id="results-display-container" style="margin-top: 1.5rem;">
|
|
12
|
+
<header>
|
|
13
|
+
<h5>Execution Results</h5>
|
|
14
|
+
</header>
|
|
15
|
+
<div id="results-display">
|
|
16
|
+
<p><small>Results will appear here after running the Flock.</small></p>
|
|
17
|
+
</div>
|
|
18
|
+
</section>
|
|
19
|
+
</article>
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
{% if flock_files %}
|
|
2
|
+
<ul class="item-list">
|
|
3
|
+
{% for file_name in flock_files %}
|
|
4
|
+
<li hx-post="/ui/load-flock-action/by-name"
|
|
5
|
+
hx-vals='{"selected_flock_filename": "{{ file_name }}"}'
|
|
6
|
+
{# After successful load, the main.py route for by-name will now return
|
|
7
|
+
the flock properties form targeted to the main content area AND
|
|
8
|
+
trigger flockLoaded event for the sidebar.
|
|
9
|
+
For the right pane of *this* view, we might want to show file details.
|
|
10
|
+
Let's assume for now loading a flock navigates to the editor.
|
|
11
|
+
If we want to show details *here*, the target would be #flock-file-detail-or-upload
|
|
12
|
+
#}
|
|
13
|
+
hx-target="#main-content-area" {# This will load the editor page content #}
|
|
14
|
+
hx-swap="innerHTML"
|
|
15
|
+
hx-indicator="#flock-file-list-loading-indicator"
|
|
16
|
+
hx-push-url="/ui/editor/properties"> {# Push URL to editor after load #}
|
|
17
|
+
{{ file_name }}
|
|
18
|
+
</li>
|
|
19
|
+
{% endfor %}
|
|
20
|
+
</ul>
|
|
21
|
+
{% else %}
|
|
22
|
+
<p style="padding: 1rem;">No Flock files found. Create one or upload.</p>
|
|
23
|
+
{% endif %}
|
|
24
|
+
<div id="flock-file-list-loading-indicator" class="htmx-indicator" style="text-align:center;"><progress indeterminate></progress></div>
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
<article id="flock-properties-form-article">
|
|
2
|
+
<header>
|
|
3
|
+
<h4>Flock Properties {% if current_filename %}(Current File: <code>{{ current_filename }}</code>){% else %}(Unsaved Flock){% endif %}</h4>
|
|
4
|
+
</header>
|
|
5
|
+
|
|
6
|
+
{% if update_message %}
|
|
7
|
+
<div class="form-message {{ 'success' if success else 'error' }}" role="alert"
|
|
8
|
+
x-data="{ show: true }" x-show="show" x-init="setTimeout(() => show = false, 3000)"
|
|
9
|
+
x-transition:leave="transition ease-in duration-300"
|
|
10
|
+
x-transition:leave-start="opacity-100"
|
|
11
|
+
x-transition:leave-end="opacity-0">
|
|
12
|
+
{{ update_message }}
|
|
13
|
+
</div>
|
|
14
|
+
{% endif %}
|
|
15
|
+
{% if save_message %}
|
|
16
|
+
<div class="form-message {{ 'success' if success else 'error' }}" role="alert"
|
|
17
|
+
x-data="{ show: true }" x-show="show" x-init="setTimeout(() => show = false, 3000)"
|
|
18
|
+
x-transition:leave="transition ease-in duration-300"
|
|
19
|
+
x-transition:leave-start="opacity-100"
|
|
20
|
+
x-transition:leave-end="opacity-0">
|
|
21
|
+
{{ save_message }}
|
|
22
|
+
</div>
|
|
23
|
+
{% endif %}
|
|
24
|
+
|
|
25
|
+
<form hx-post="/api/flocks/htmx/flock-properties" hx-target="#flock-properties-form-article" hx-swap="innerHTML" hx-indicator="#flock-props-loading">
|
|
26
|
+
<label for="flock_name">Flock Name</label>
|
|
27
|
+
<input type="text" id="flock_name" name="flock_name" value="{{ flock.name if flock else '' }}" required>
|
|
28
|
+
|
|
29
|
+
<label for="default_model">Default Model</label>
|
|
30
|
+
<input type="text" id="default_model" name="default_model" value="{{ flock.model if flock and flock.model else '' }}" placeholder="e.g., openai/gpt-4o">
|
|
31
|
+
|
|
32
|
+
<label for="description">Description</label>
|
|
33
|
+
<textarea id="description" name="description" placeholder="A brief description of this Flock.">{{ flock.description if flock and flock.description else '' }}</textarea>
|
|
34
|
+
|
|
35
|
+
<div class="grid">
|
|
36
|
+
<button type="submit">Update Properties <span id="flock-props-loading" class="htmx-indicator"><progress indeterminate></progress></span></button>
|
|
37
|
+
</div>
|
|
38
|
+
</form>
|
|
39
|
+
<hr>
|
|
40
|
+
<form hx-post="/api/flocks/htmx/save-flock" hx-target="#flock-properties-form-article" hx-swap="innerHTML" hx-indicator="#flock-save-loading">
|
|
41
|
+
<label for="save_filename">Save Flock As:</label>
|
|
42
|
+
<input type="text" id="save_filename" name="save_filename"
|
|
43
|
+
value="{{ current_filename if current_filename else (flock.name.replace(' ', '_').lower() + '.flock.yaml' if flock and flock.name else 'my_flock.flock.yaml') }}"
|
|
44
|
+
required
|
|
45
|
+
placeholder="filename.flock.yaml">
|
|
46
|
+
<small>Will save to <code>./.flock_ui_projects/</code>. Use <code>.flock.yaml</code>, <code>.yaml</code>, or <code>.yml</code>.</small>
|
|
47
|
+
<div class="grid">
|
|
48
|
+
<button type="submit">Save to File <span id="flock-save-loading" class="htmx-indicator"><progress indeterminate></progress></span></button>
|
|
49
|
+
</div>
|
|
50
|
+
</form>
|
|
51
|
+
</article>
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
<article>
|
|
2
|
+
<header>
|
|
3
|
+
<h5>Upload New Flock File</h5>
|
|
4
|
+
</header>
|
|
5
|
+
<form hx-post="/ui/load-flock-action/by-upload"
|
|
6
|
+
hx-target="#main-content-area" {# After upload, go to editor #}
|
|
7
|
+
hx-swap="innerHTML"
|
|
8
|
+
hx-encoding="multipart/form-data"
|
|
9
|
+
hx-indicator="#upload-loading-indicator-pane">
|
|
10
|
+
<label for="flock_file_upload_pane">Upload <code>.flock.yaml</code>, <code>.yaml</code>, or <code>.yml</code> file:</label>
|
|
11
|
+
<input type="file" id="flock_file_upload_pane" name="flock_file_upload" accept=".yaml,.yml,.flock" required>
|
|
12
|
+
<button type="submit">Upload and Load Flock</button>
|
|
13
|
+
<span id="upload-loading-indicator-pane" class="htmx-indicator"><progress indeterminate></progress> Uploading...</span>
|
|
14
|
+
</form>
|
|
15
|
+
{# Optionally, if a file from the list was clicked to show details before loading: #}
|
|
16
|
+
{# {% if selected_file_details %} ... display details ... {% endif %} #}
|
|
17
|
+
</article>
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
<article id="dashboard-flock-manager-content">
|
|
2
|
+
<header>
|
|
3
|
+
<h3>Manage & Load Flocks</h3>
|
|
4
|
+
</header>
|
|
5
|
+
|
|
6
|
+
{% if error_message %}
|
|
7
|
+
<div class="error DANGER" role="alert" x-data="{ show: true }" x-show="show" x-init="setTimeout(() => show = false, 5000)">
|
|
8
|
+
{{ error_message }} <button type="button" class="close" @click="show = false">×</button>
|
|
9
|
+
</div>
|
|
10
|
+
{% endif %}
|
|
11
|
+
{% if success_message %}
|
|
12
|
+
<div class="success SUCCESS" role="alert" x-data="{ show: true }" x-show="show" x-init="setTimeout(() => show = false, 5000)">
|
|
13
|
+
{{ success_message }} <button type="button" class="close" @click="show = false">×</button>
|
|
14
|
+
</div>
|
|
15
|
+
{% endif %}
|
|
16
|
+
|
|
17
|
+
<div class="flock-manager-grid">
|
|
18
|
+
<section id="flock-file-list-column" class="list-pane">
|
|
19
|
+
<header style="padding: 0.5rem 1rem; border-bottom: 1px solid var(--pico-muted-border-color);">
|
|
20
|
+
<h6>Available Flock Files</h6>
|
|
21
|
+
<small>(in <code>./.flock_ui_projects/</code>)</small>
|
|
22
|
+
</header>
|
|
23
|
+
<div hx-get="/ui/htmx/dashboard-flock-file-list"
|
|
24
|
+
hx-trigger="load, flockFileListChanged from:body"
|
|
25
|
+
hx-swap="innerHTML"
|
|
26
|
+
id="dashboard-flock-file-list-target">
|
|
27
|
+
<p style="padding:1rem;">Loading files...</p><progress indeterminate></progress>
|
|
28
|
+
</div>
|
|
29
|
+
</section>
|
|
30
|
+
|
|
31
|
+
<section id="flock-detail-action-column" class="detail-pane">
|
|
32
|
+
{# This area will be updated when a file is selected from the list. #}
|
|
33
|
+
<div id="flock-properties-or-action-content">
|
|
34
|
+
<article style="text-align:center; margin-top: 2rem; border: none; background: transparent;">
|
|
35
|
+
<p>Select a Flock from the list to view its details and load it into the editor.</p>
|
|
36
|
+
<p><small>To create a new Flock or upload an existing one, use the options in the sidebar.</small></p>
|
|
37
|
+
</article>
|
|
38
|
+
</div>
|
|
39
|
+
</section>
|
|
40
|
+
</div>
|
|
41
|
+
</article>
|
|
42
|
+
|
|
43
|
+
<style>
|
|
44
|
+
/* Styles for the dashboard's two-pane layout for flock management */
|
|
45
|
+
.flock-manager-grid {
|
|
46
|
+
display: grid;
|
|
47
|
+
grid-template-columns: minmax(280px, 1fr) 2.5fr;
|
|
48
|
+
gap: 0;
|
|
49
|
+
height: calc(100vh - var(--header-height) - 6rem);
|
|
50
|
+
border: 1px solid var(--pico-muted-border-color);
|
|
51
|
+
border-radius: var(--pico-border-radius);
|
|
52
|
+
background-color: var(--pico-card-background-color);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
.flock-manager-grid .list-pane {
|
|
56
|
+
border-right: 1px solid var(--pico-muted-border-color);
|
|
57
|
+
padding: 0;
|
|
58
|
+
overflow-y: auto;
|
|
59
|
+
display: flex;
|
|
60
|
+
flex-direction: column;
|
|
61
|
+
}
|
|
62
|
+
.flock-manager-grid .list-pane header {
|
|
63
|
+
flex-shrink: 0;
|
|
64
|
+
}
|
|
65
|
+
.flock-manager-grid .list-pane #dashboard-flock-file-list-target {
|
|
66
|
+
flex-grow: 1;
|
|
67
|
+
overflow-y: auto;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
.flock-manager-grid .detail-pane {
|
|
71
|
+
padding: 1rem;
|
|
72
|
+
overflow-y: auto;
|
|
73
|
+
background-color: var(--pico-background-color);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
#dashboard-flock-file-list-target ul.item-list {
|
|
77
|
+
list-style-type: none; padding: 0; margin:0;
|
|
78
|
+
}
|
|
79
|
+
#dashboard-flock-file-list-target li {
|
|
80
|
+
padding: 0.75rem 1rem; border-bottom: 1px solid var(--pico-muted-border-color);
|
|
81
|
+
cursor: pointer; transition: background-color 0.15s ease-in-out;
|
|
82
|
+
}
|
|
83
|
+
#dashboard-flock-file-list-target li:last-child { border-bottom: none; }
|
|
84
|
+
#dashboard-flock-file-list-target li:hover,
|
|
85
|
+
#dashboard-flock-file-list-target li.selected-item {
|
|
86
|
+
background-color: var(--pico-primary-focus); color: var(--pico-primary-inverse);
|
|
87
|
+
}
|
|
88
|
+
</style>
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
<article style="margin-top:0; padding-top:0;"> {# Remove top margin/padding from article to align with buttons #}
|
|
2
|
+
<header>
|
|
3
|
+
<h4 style="margin-bottom: 0.5rem;">{{ item_type_display }}</h4>
|
|
4
|
+
</header>
|
|
5
|
+
{% if items %}
|
|
6
|
+
<table>
|
|
7
|
+
<thead>
|
|
8
|
+
<tr>
|
|
9
|
+
<th>Name</th>
|
|
10
|
+
<th>Module Path</th>
|
|
11
|
+
</tr>
|
|
12
|
+
</thead>
|
|
13
|
+
<tbody>
|
|
14
|
+
{% for item in items %}
|
|
15
|
+
<tr>
|
|
16
|
+
<td>{{ item.name }}</td>
|
|
17
|
+
<td>{{ item.module }}</td>
|
|
18
|
+
</tr>
|
|
19
|
+
{% endfor %}
|
|
20
|
+
</tbody>
|
|
21
|
+
</table>
|
|
22
|
+
{% else %}
|
|
23
|
+
<p>No {{ item_type_display.lower() }} found in the registry.</p>
|
|
24
|
+
{% endif %}
|
|
25
|
+
</article>
|