flock-core 0.4.0b49__py3-none-any.whl → 0.4.1__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/adapter/__init__.py +14 -0
- flock/adapter/azure_adapter.py +68 -0
- flock/adapter/chroma_adapter.py +73 -0
- flock/adapter/faiss_adapter.py +97 -0
- flock/adapter/pinecone_adapter.py +51 -0
- flock/adapter/vector_base.py +47 -0
- flock/config.py +1 -1
- flock/core/context/context.py +20 -0
- flock/core/flock.py +71 -91
- flock/core/flock_agent.py +58 -3
- flock/core/flock_module.py +5 -0
- flock/di.py +41 -0
- flock/modules/enterprise_memory/README.md +99 -0
- flock/modules/enterprise_memory/enterprise_memory_module.py +526 -0
- flock/modules/mem0/mem0_module.py +79 -16
- flock/modules/mem0_async/async_mem0_module.py +126 -0
- flock/modules/memory/memory_module.py +28 -8
- flock/modules/performance/metrics_module.py +24 -1
- flock/modules/zep/__init__.py +1 -0
- flock/modules/zep/zep_module.py +192 -0
- flock/webapp/app/api/execution.py +108 -73
- flock/webapp/app/chat.py +96 -12
- flock/webapp/app/config.py +1 -1
- flock/webapp/app/main.py +14 -12
- flock/webapp/app/services/sharing_models.py +38 -0
- flock/webapp/app/services/sharing_store.py +60 -1
- flock/webapp/static/css/chat.css +2 -0
- flock/webapp/templates/base.html +91 -1
- flock/webapp/templates/chat.html +64 -1
- flock/webapp/templates/partials/_agent_detail_form.html +3 -3
- flock/webapp/templates/partials/_chat_messages.html +50 -4
- flock/webapp/templates/partials/_flock_properties_form.html +2 -2
- flock/webapp/templates/partials/_results_display.html +54 -11
- flock/webapp/templates/partials/_structured_data_view.html +2 -2
- flock/webapp/templates/shared_run_page.html +27 -0
- {flock_core-0.4.0b49.dist-info → flock_core-0.4.1.dist-info}/METADATA +6 -4
- {flock_core-0.4.0b49.dist-info → flock_core-0.4.1.dist-info}/RECORD +41 -30
- flock/modules/mem0graph/mem0_graph_module.py +0 -63
- /flock/modules/{mem0graph → mem0_async}/__init__.py +0 -0
- {flock_core-0.4.0b49.dist-info → flock_core-0.4.1.dist-info}/WHEEL +0 -0
- {flock_core-0.4.0b49.dist-info → flock_core-0.4.1.dist-info}/entry_points.txt +0 -0
- {flock_core-0.4.0b49.dist-info → flock_core-0.4.1.dist-info}/licenses/LICENSE +0 -0
flock/webapp/templates/base.html
CHANGED
|
@@ -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;">×</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
|
|
flock/webapp/templates/chat.html
CHANGED
|
@@ -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;">×</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">
|
|
@@ -5,9 +5,55 @@
|
|
|
5
5
|
<span class="chat-timestamp">{{ entry.timestamp|default(now().strftime('%H:%M')) }}</span>
|
|
6
6
|
</div>
|
|
7
7
|
{% else %}
|
|
8
|
-
<div class="bubble bot">
|
|
9
|
-
|
|
10
|
-
<
|
|
8
|
+
<div class="bubble bot" x-data="{showForm:false}">
|
|
9
|
+
<!-- Bubble content (visible when feedback form hidden) -->
|
|
10
|
+
<div x-show="!showForm">
|
|
11
|
+
<div>
|
|
12
|
+
{{ entry.text | safe }}
|
|
13
|
+
<span class="chat-timestamp">
|
|
14
|
+
{{ entry.timestamp|default(now().strftime('%H:%M')) }}{% if entry.agent %} - {{ entry.agent }}{% endif %}{% if entry.duration_ms is defined %} - {{ entry.duration_ms }}ms - {% endif %}
|
|
15
|
+
<!-- hidden meta form (used by thumbs links) -->
|
|
16
|
+
<form class="feedback-meta" style="display:none">
|
|
17
|
+
{% if share_id %}<input type="hidden" name="share_id" value="{{ share_id }}">{% endif %}
|
|
18
|
+
<input type="hidden" name="flock_definition" value="{{ entry.flock_yaml | replace('"', '"') }}">
|
|
19
|
+
<input type="hidden" name="agent_name" value="{{ entry.agent }}">
|
|
20
|
+
<input type="hidden" name="actual_response" value='{{ entry.raw_json | replace("'", "'") }}'>
|
|
21
|
+
<input type="hidden" name="reason" value="positive">
|
|
22
|
+
</form>
|
|
23
|
+
|
|
24
|
+
<a href="#"
|
|
25
|
+
hx-post="{% if share_id %}/chat/htmx/feedback-shared{% else %}/chat/htmx/feedback{% endif %}"
|
|
26
|
+
hx-include="closest .feedback-meta"
|
|
27
|
+
hx-target="closest .bubble"
|
|
28
|
+
hx-swap="innerHTML"
|
|
29
|
+
title="Looks good!" class="feedback-link">👍</a>
|
|
30
|
+
-
|
|
31
|
+
<a href="#" @click.prevent="showForm=true" title="Submit detailed feedback" class="feedback-link">👎</a>
|
|
32
|
+
</span>
|
|
33
|
+
</div>
|
|
34
|
+
</div>
|
|
35
|
+
|
|
36
|
+
<!-- Feedback form (initially hidden, toggled by 👎 link) -->
|
|
37
|
+
<div x-show="showForm" style="width:800px;">
|
|
38
|
+
<form
|
|
39
|
+
hx-post="{% if share_id %}/chat/htmx/feedback-shared{% else %}/chat/htmx/feedback{% endif %}"
|
|
40
|
+
hx-swap="outerHTML"
|
|
41
|
+
x-on:htmx:afterRequest="showForm=false"
|
|
42
|
+
style="display:block; width:800px;">
|
|
43
|
+
{% if share_id %}<input type="hidden" name="share_id" value="{{ share_id }}">{% endif %}
|
|
44
|
+
<input type="hidden" name="flock_definition" value='{{ entry.flock_yaml | tojson | safe }}'>
|
|
45
|
+
<input type="hidden" name="agent_name" value='{{ entry.agent | tojson | safe }}'>
|
|
46
|
+
<input type="hidden" name="actual_response" value='{{ entry.raw_json | tojson | safe }}'>
|
|
47
|
+
<label>Reason</label>
|
|
48
|
+
<textarea name="reason" required style="min-height:5rem;width:100%; white-space:pre-wrap;"></textarea>
|
|
49
|
+
<label>Expected / Correct Response</label>
|
|
50
|
+
<textarea name="expected_response" style="min-height:12rem;width:100%; white-space:pre-wrap;font-family:monospace;">{{ entry.raw_json }}</textarea>
|
|
51
|
+
<div style="margin-top:0.4rem; display:flex; gap:0.5rem;">
|
|
52
|
+
<button type="submit" class="secondary">Send</button>
|
|
53
|
+
<button type="button" class="outline" @click="showForm=false">Back...</button>
|
|
54
|
+
</div>
|
|
55
|
+
</form>
|
|
56
|
+
</div>
|
|
11
57
|
</div>
|
|
12
58
|
{% endif %}
|
|
13
|
-
{% endfor %}
|
|
59
|
+
{% endfor %}
|
|
@@ -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') }}"
|
|
@@ -6,30 +6,73 @@
|
|
|
6
6
|
<div style="text-align: right;">
|
|
7
7
|
<button role="button" class="outline contrast" @click="viewMode = 'structured'" :aria-pressed="viewMode === 'structured'">Structured</button>
|
|
8
8
|
<button role="button" class="outline contrast" @click="viewMode = 'json'" :aria-pressed="viewMode === 'json'">Raw JSON</button>
|
|
9
|
+
|
|
10
|
+
<div style="display:inline-block;margin-left:0.5rem;">
|
|
11
|
+
<!-- Quick thumbs-up feedback (inline form so we have the identifiers) -->
|
|
12
|
+
<form hx-post="{{ feedback_endpoint }}" hx-target="#results-display-content" hx-swap="innerHTML" style="display:inline-block;vertical-align:middle;margin:0;" hx-indicator="#feedback-loading-indicator">
|
|
13
|
+
{% if share_id %}<input type="hidden" name="share_id" value="{{ share_id }}">{% endif %}
|
|
14
|
+
<input type="hidden" name="flock_name" value="{{ flock_name }}">
|
|
15
|
+
<input type="hidden" name="agent_name" value="{{ agent_name }}">
|
|
16
|
+
<input type="hidden" name="flock_definition" value='{{ flock_definition | replace("'", "'") }}'>
|
|
17
|
+
<input type="hidden" name="actual_response" value='{{ result_raw_json | replace("'", "'") }}'>
|
|
18
|
+
<input type="hidden" name="reason" value="positive">
|
|
19
|
+
<button type="submit" role="button" class="outline contrast" title="Looks good!" style="padding:0.3rem 0.5rem;line-height:1;vertical-align:middle;margin:0;"><i class="fa fa-thumbs-up"></i></button>
|
|
20
|
+
</form>
|
|
21
|
+
|
|
22
|
+
<!-- Thumbs-down toggles detailed feedback form -->
|
|
23
|
+
<button role="button" class="outline contrast" @click="viewMode = 'feedback'" :aria-pressed="viewMode === 'feedback'" title="Something's wrong" style="padding:0.3rem 0.5rem;line-height:1;vertical-align:middle;margin:0;"><i class="fa fa-thumbs-down"></i></button>
|
|
24
|
+
</div>
|
|
9
25
|
</div>
|
|
10
26
|
</header>
|
|
11
27
|
|
|
12
28
|
<div x-show="viewMode === 'json'">
|
|
13
|
-
{
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
29
|
+
{# Check for the new result_raw_json variable first #}
|
|
30
|
+
{% if result_raw_json is defined %}
|
|
31
|
+
<pre><code class="language-json" style="word-break: break-all; white-space: pre-wrap;">{{ result_raw_json }}</code></pre>
|
|
32
|
+
{# Fallback for old context or if result was an error string from backend before formatting #}
|
|
33
|
+
{% elif result is string %}
|
|
34
|
+
<pre><code class="language-plaintext" style="word-break: break-all; white-space: pre-wrap;">{{ result }}</code></pre>
|
|
35
|
+
{% elif result %}
|
|
36
|
+
{# Fallback if result_raw_json is somehow not provided but result (dict) is #}
|
|
37
|
+
<pre><code class="language-json" style="word-break: break-all; white-space: pre-wrap;">{{ result | tojson(indent=2) }}</code></pre>
|
|
17
38
|
{% else %}
|
|
18
39
|
<p>No results to display yet.</p>
|
|
19
40
|
{% endif %}
|
|
20
41
|
</div>
|
|
21
42
|
|
|
22
43
|
<div x-show="viewMode === 'structured'">
|
|
23
|
-
{% if
|
|
24
|
-
<p class="error" style="white-space: pre-wrap;">{{
|
|
25
|
-
{% elif
|
|
26
|
-
{
|
|
27
|
-
|
|
28
|
-
{% elif result_data %}
|
|
44
|
+
{% if result is string %}
|
|
45
|
+
<p class="error" style="white-space: pre-wrap;">{{ result }}</p>
|
|
46
|
+
{% elif result is mapping %}
|
|
47
|
+
{{ render_value(result) }}
|
|
48
|
+
{% elif result %}
|
|
29
49
|
<p>Structured view not available for this result type (not a dictionary).</p>
|
|
30
|
-
<pre><code>{{
|
|
50
|
+
<pre><code class="language-json" style="word-break: break-all; white-space: pre-wrap;">{{ result | tojson(indent=2) }}</code></pre>
|
|
31
51
|
{% else %}
|
|
32
52
|
<p>No results to display yet.</p>
|
|
33
53
|
{% endif %}
|
|
34
54
|
</div>
|
|
55
|
+
|
|
56
|
+
<!-- ---------------- Feedback form ---------------- -->
|
|
57
|
+
<div x-show="viewMode === 'feedback'" style="margin-top: 1rem;">
|
|
58
|
+
<form hx-post="{{ feedback_endpoint }}" hx-target="#results-display-content" hx-swap="innerHTML" hx-indicator="#feedback-loading-indicator">
|
|
59
|
+
{# Hidden identifiers #}
|
|
60
|
+
{% if share_id %}
|
|
61
|
+
<input type="hidden" name="share_id" value="{{ share_id }}">
|
|
62
|
+
{% endif %}
|
|
63
|
+
<input type="hidden" name="flock_name" value="{{ flock_name }}">
|
|
64
|
+
<input type="hidden" name="agent_name" value="{{ agent_name }}">
|
|
65
|
+
<input type="hidden" name="flock_definition" value='{{ flock_definition | replace("'", "'") }}'>
|
|
66
|
+
<input type="hidden" name="actual_response" value='{{ result_raw_json | replace("'", "'") }}'>
|
|
67
|
+
|
|
68
|
+
<label for="feedback_reason">Reason / Comment</label>
|
|
69
|
+
<textarea id="feedback_reason" name="reason" placeholder="Why isn't the answer good?" required style="min-height:6rem;"></textarea>
|
|
70
|
+
|
|
71
|
+
<label for="expected_response" style="margin-top:0.5rem;">Correct / Expected Response (JSON or text)</label>
|
|
72
|
+
<textarea id="expected_response" name="expected_response" style="white-space: pre; font-family: monospace; min-height:10rem;">{{ result_raw_json }}</textarea>
|
|
73
|
+
|
|
74
|
+
<button type="submit" class="secondary" style="margin-top:0.5rem;">Send Feedback</button>
|
|
75
|
+
<span id="feedback-loading-indicator" class="htmx-indicator"><progress indeterminate></progress> Sending…</span>
|
|
76
|
+
</form>
|
|
77
|
+
</div>
|
|
35
78
|
</article>
|
|
@@ -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
|
-
<
|
|
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.
|
|
3
|
+
Version: 0.4.1
|
|
4
4
|
Summary: Declarative LLM Orchestration at Scale
|
|
5
5
|
Author-email: Andre Ratzenberger <andre.ratzenberger@whiteduck.de>
|
|
6
6
|
License-File: LICENSE
|
|
@@ -21,7 +21,7 @@ Requires-Dist: litellm==1.69.3
|
|
|
21
21
|
Requires-Dist: loguru>=0.7.3
|
|
22
22
|
Requires-Dist: markdown2>=2.5.3
|
|
23
23
|
Requires-Dist: matplotlib>=3.10.0
|
|
24
|
-
Requires-Dist: mem0ai[graph]>=0.1.
|
|
24
|
+
Requires-Dist: mem0ai[graph]>=0.1.101
|
|
25
25
|
Requires-Dist: msgpack>=1.1.0
|
|
26
26
|
Requires-Dist: notion-client>=2.3.0
|
|
27
27
|
Requires-Dist: openai==1.75.0
|
|
@@ -50,6 +50,8 @@ Requires-Dist: tiktoken>=0.8.0
|
|
|
50
50
|
Requires-Dist: toml>=0.10.2
|
|
51
51
|
Requires-Dist: tqdm>=4.67.1
|
|
52
52
|
Requires-Dist: uvicorn>=0.34.0
|
|
53
|
+
Requires-Dist: wd-di>=0.2.14
|
|
54
|
+
Requires-Dist: zep-python>=2.0.2
|
|
53
55
|
Provides-Extra: all-tools
|
|
54
56
|
Requires-Dist: azure-identity>=1.23.0; extra == 'all-tools'
|
|
55
57
|
Requires-Dist: azure-search-documents>=11.5.2; extra == 'all-tools'
|
|
@@ -91,7 +93,7 @@ Description-Content-Type: text/markdown
|
|
|
91
93
|
|
|
92
94
|
🐤 `pip install flock-core` will install the latest non-beta version 🐤
|
|
93
95
|
|
|
94
|
-
🐤
|
|
96
|
+
🐤 The 0.4.0 Magpie release is in the works! 🐤
|
|
95
97
|
|
|
96
98
|
---
|
|
97
99
|
|
|
@@ -296,7 +298,7 @@ Flock makes this easy with:
|
|
|
296
298
|
* **Declarative Configuration:** Define Temporal timeouts, retry policies, and task queues directly within your `Flock` and `FlockAgent` configurations (YAML or Python).
|
|
297
299
|
* **Correct Patterns:** Uses Temporal's recommended granular activity execution for better control and visibility.
|
|
298
300
|
* **Clear Worker Separation:** Provides guidance and flags for running dedicated Temporal workers, separating development convenience from production best practices.
|
|
299
|
-
|
|
301
|
+
|
|
300
302
|
Visit the [Temporal Documentation](https://learn.temporal.io/python/workflows/) for more information on how to use Temporal.
|
|
301
303
|
|
|
302
304
|
Or check out the [Flock Showcase](https://github.com/whiteducksoftware/flock-showcase) for a complete example of a Flock that uses Temporal or our [docs](https://whiteducksoftware.github.io/flock/guides/temporal-configuration/) for more information.
|