flock-core 0.4.0b32__py3-none-any.whl → 0.4.0b34__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/core/flock_agent.py +11 -4
- flock/core/flock_module.py +3 -3
- flock/core/util/cli_helper.py +3 -3
- flock/core/util/spliter.py +139 -54
- {flock_core-0.4.0b32.dist-info → flock_core-0.4.0b34.dist-info}/METADATA +1 -1
- {flock_core-0.4.0b32.dist-info → flock_core-0.4.0b34.dist-info}/RECORD +9 -9
- {flock_core-0.4.0b32.dist-info → flock_core-0.4.0b34.dist-info}/WHEEL +0 -0
- {flock_core-0.4.0b32.dist-info → flock_core-0.4.0b34.dist-info}/entry_points.txt +0 -0
- {flock_core-0.4.0b32.dist-info → flock_core-0.4.0b34.dist-info}/licenses/LICENSE +0 -0
flock/core/flock_agent.py
CHANGED
|
@@ -231,13 +231,17 @@ class FlockAgent(BaseModel, Serializable, DSPyIntegrationMixin, ABC):
|
|
|
231
231
|
agent=self.name,
|
|
232
232
|
)
|
|
233
233
|
try:
|
|
234
|
+
current_result = result
|
|
234
235
|
for module in self.get_enabled_modules():
|
|
235
|
-
await module.on_terminate(
|
|
236
|
-
self, inputs, self.context,
|
|
236
|
+
tmp_result = await module.on_terminate(
|
|
237
|
+
self, inputs, self.context, current_result
|
|
237
238
|
)
|
|
239
|
+
# If the module returns a result, use it
|
|
240
|
+
if tmp_result:
|
|
241
|
+
current_result = tmp_result
|
|
238
242
|
|
|
239
243
|
if self.write_to_file:
|
|
240
|
-
self._save_output(self.name,
|
|
244
|
+
self._save_output(self.name, current_result)
|
|
241
245
|
|
|
242
246
|
if self.wait_for_input:
|
|
243
247
|
# simple input prompt
|
|
@@ -318,12 +322,15 @@ class FlockAgent(BaseModel, Serializable, DSPyIntegrationMixin, ABC):
|
|
|
318
322
|
# Post-evaluate hooks
|
|
319
323
|
current_result = result
|
|
320
324
|
for module in self.get_enabled_modules():
|
|
321
|
-
|
|
325
|
+
tmp_result = await module.on_post_evaluate(
|
|
322
326
|
self,
|
|
323
327
|
current_inputs,
|
|
324
328
|
self.context,
|
|
325
329
|
current_result,
|
|
326
330
|
)
|
|
331
|
+
# If the module returns a result, use it
|
|
332
|
+
if tmp_result:
|
|
333
|
+
current_result = tmp_result
|
|
327
334
|
|
|
328
335
|
logger.debug(f"Evaluation completed for agent '{self.name}'")
|
|
329
336
|
return current_result
|
flock/core/flock_module.py
CHANGED
|
@@ -76,7 +76,7 @@ class FlockModule(BaseModel, ABC):
|
|
|
76
76
|
inputs: dict[str, Any],
|
|
77
77
|
context: FlockContext | None = None,
|
|
78
78
|
result: dict[str, Any] | None = None,
|
|
79
|
-
) -> dict[str, Any]:
|
|
79
|
+
) -> dict[str, Any] | None:
|
|
80
80
|
"""Called after agent evaluation, can modify results."""
|
|
81
81
|
return result
|
|
82
82
|
|
|
@@ -86,9 +86,9 @@ class FlockModule(BaseModel, ABC):
|
|
|
86
86
|
inputs: dict[str, Any],
|
|
87
87
|
context: FlockContext | None = None,
|
|
88
88
|
result: dict[str, Any] | None = None,
|
|
89
|
-
) -> None:
|
|
89
|
+
) -> dict[str, Any] | None:
|
|
90
90
|
"""Called when the agent finishes running."""
|
|
91
|
-
|
|
91
|
+
return result
|
|
92
92
|
|
|
93
93
|
async def on_error(
|
|
94
94
|
self,
|
flock/core/util/cli_helper.py
CHANGED
|
@@ -62,9 +62,9 @@ def init_console(clear_screen: bool = True, show_banner: bool = True):
|
|
|
62
62
|
|
|
63
63
|
if show_banner:
|
|
64
64
|
console.print(banner_text)
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
65
|
+
console.print(
|
|
66
|
+
"[italic]'Magpie'[/] milestone - [bold]white duck GmbH[/] - [cyan]https://whiteduck.de[/]\n"
|
|
67
|
+
)
|
|
68
68
|
|
|
69
69
|
|
|
70
70
|
def display_banner_no_version():
|
flock/core/util/spliter.py
CHANGED
|
@@ -2,46 +2,37 @@ import re
|
|
|
2
2
|
|
|
3
3
|
|
|
4
4
|
def split_top_level(spec: str) -> list[str]:
|
|
5
|
-
"""
|
|
6
|
-
are **not** inside brackets, braces, parentheses, string literals,
|
|
7
|
-
or the free-form description).
|
|
8
|
-
|
|
9
|
-
Strategy
|
|
10
|
-
--------
|
|
11
|
-
1. Single pass, char-by-char.
|
|
12
|
-
2. Track • nesting depth for (), [], {}
|
|
13
|
-
• whether we are inside a quoted string
|
|
14
|
-
3. Consider a comma a separator *only* if depth == 0, we are not
|
|
15
|
-
inside quotes **and** the text that follows matches
|
|
16
|
-
`optional-ws + identifier + optional-ws + ':'`
|
|
17
|
-
which can only be the start of the next field.
|
|
18
|
-
"""
|
|
5
|
+
"""Return raw field strings, split on *top-level* commas."""
|
|
19
6
|
fields: list[str] = []
|
|
20
7
|
start = 0
|
|
21
8
|
depth = 0
|
|
22
9
|
quote_char: str | None = None
|
|
23
10
|
i = 0
|
|
24
|
-
ident_re = re.compile(r"[A-Za-z_]\w*") # cheap
|
|
11
|
+
ident_re = re.compile(r"[A-Za-z_]\w*") # cheap identifier
|
|
25
12
|
|
|
26
13
|
while i < len(spec):
|
|
27
14
|
ch = spec[i]
|
|
28
15
|
|
|
29
|
-
#
|
|
16
|
+
# ---------- string handling ----------
|
|
30
17
|
if quote_char:
|
|
18
|
+
if ch == "\\":
|
|
19
|
+
i += 2 # skip escaped char
|
|
20
|
+
continue
|
|
31
21
|
if ch == quote_char:
|
|
32
22
|
quote_char = None
|
|
33
23
|
i += 1
|
|
34
24
|
continue
|
|
35
25
|
|
|
36
26
|
if ch in {"'", '"'}:
|
|
37
|
-
# treat as string delimiter only in places regular Python would
|
|
38
27
|
prev = spec[i - 1] if i else " "
|
|
39
|
-
if
|
|
28
|
+
if (
|
|
29
|
+
depth or prev.isspace() or prev in "=([{,:"
|
|
30
|
+
): # looks like a quote
|
|
40
31
|
quote_char = ch
|
|
41
32
|
i += 1
|
|
42
33
|
continue
|
|
43
34
|
|
|
44
|
-
#
|
|
35
|
+
# ---------- bracket / brace / paren ----------
|
|
45
36
|
if ch in "([{":
|
|
46
37
|
depth += 1
|
|
47
38
|
i += 1
|
|
@@ -51,23 +42,28 @@ def split_top_level(spec: str) -> list[str]:
|
|
|
51
42
|
i += 1
|
|
52
43
|
continue
|
|
53
44
|
|
|
54
|
-
#
|
|
45
|
+
# ---------- field separators ----------
|
|
55
46
|
if ch == "," and depth == 0:
|
|
56
47
|
j = i + 1
|
|
57
48
|
while j < len(spec) and spec[j].isspace():
|
|
58
49
|
j += 1
|
|
59
|
-
if j
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
50
|
+
if j >= len(spec): # comma at end – split
|
|
51
|
+
fields.append(spec[start:i].strip())
|
|
52
|
+
start = i + 1
|
|
53
|
+
i += 1
|
|
54
|
+
continue
|
|
55
|
+
|
|
56
|
+
id_match = ident_re.match(spec, j)
|
|
57
|
+
if id_match:
|
|
58
|
+
k = id_match.end()
|
|
59
|
+
while k < len(spec) and spec[k].isspace():
|
|
60
|
+
k += 1
|
|
61
|
+
if k >= len(spec) or spec[k] in {":", "|", ","}:
|
|
62
|
+
# confirmed: comma separates two fields
|
|
63
|
+
fields.append(spec[start:i].strip())
|
|
64
|
+
start = i + 1
|
|
65
|
+
i += 1
|
|
66
|
+
continue
|
|
71
67
|
|
|
72
68
|
i += 1
|
|
73
69
|
|
|
@@ -76,21 +72,29 @@ def split_top_level(spec: str) -> list[str]:
|
|
|
76
72
|
|
|
77
73
|
|
|
78
74
|
def parse_schema(spec: str) -> list[tuple[str, str, str]]:
|
|
79
|
-
"""Turn
|
|
75
|
+
"""Turn *spec* into a list of (name, python_type, description)."""
|
|
80
76
|
result: list[tuple[str, str, str]] = []
|
|
81
77
|
|
|
82
78
|
for field in split_top_level(spec):
|
|
83
|
-
|
|
84
|
-
|
|
79
|
+
name = ""
|
|
80
|
+
type_str = "str" # default type
|
|
81
|
+
description = ""
|
|
85
82
|
|
|
86
|
-
name_part,
|
|
87
|
-
name = name_part.strip()
|
|
88
|
-
|
|
89
|
-
type_part, _, desc_part = rest.partition("|")
|
|
90
|
-
type_str = type_part.strip()
|
|
83
|
+
name_part, _, desc_part = field.partition("|")
|
|
91
84
|
description = desc_part.strip()
|
|
85
|
+
main_part = name_part.strip()
|
|
86
|
+
|
|
87
|
+
if ":" in main_part:
|
|
88
|
+
name, type_candidate = main_part.split(":", 1)
|
|
89
|
+
name = name.strip()
|
|
90
|
+
type_candidate = type_candidate.strip()
|
|
91
|
+
if type_candidate:
|
|
92
|
+
type_str = type_candidate
|
|
93
|
+
else:
|
|
94
|
+
name = main_part # keeps default type
|
|
92
95
|
|
|
93
|
-
|
|
96
|
+
if name: # skip broken pieces
|
|
97
|
+
result.append((name, type_str, description))
|
|
94
98
|
|
|
95
99
|
return result
|
|
96
100
|
|
|
@@ -107,20 +111,101 @@ if __name__ == "__main__":
|
|
|
107
111
|
SAMPLE_2 = (
|
|
108
112
|
"field_with_internal_quotes: Literal['type_A', "
|
|
109
113
|
'"type_B_with_\'_apostrophe"] | A literal with mixed quotes,'
|
|
110
|
-
" another_field:
|
|
114
|
+
" another_field :str| A field with a description"
|
|
115
|
+
)
|
|
116
|
+
|
|
117
|
+
SAMPLE_3 = (
|
|
118
|
+
"field_with_internal_quotes: Literal['type_A', "
|
|
119
|
+
'"type_B_with_\'_apostrophe"] | A literal with mixed quotes,'
|
|
120
|
+
" another_field | A field with a description"
|
|
121
|
+
)
|
|
122
|
+
|
|
123
|
+
SAMPLE_4 = "input, query, output"
|
|
124
|
+
|
|
125
|
+
SAMPLE_5 = (
|
|
126
|
+
"name: str | The character's full name,"
|
|
127
|
+
"race: str | The character's fantasy race,"
|
|
128
|
+
"class: Literal['mage','thief'] | The character's profession, which can be either mage or thief,"
|
|
129
|
+
"background: str | A brief backstory for the character"
|
|
130
|
+
)
|
|
131
|
+
|
|
132
|
+
SAMPLE_6 = (
|
|
133
|
+
"summary: str | A short blurb, e.g. key:value pairs that appear in logs"
|
|
111
134
|
)
|
|
135
|
+
# ➜ [('summary', 'str',
|
|
136
|
+
# 'A short blurb, e.g. key:value pairs that appear in logs')]
|
|
112
137
|
|
|
113
|
-
|
|
114
|
-
print(f"Sample 2: {SAMPLE_2}")
|
|
138
|
+
SAMPLE_7 = "path: str | The literal string 'C:\\\\Program Files\\\\My,App'"
|
|
115
139
|
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
print(split_sample_1)
|
|
119
|
-
for field in split_sample_1:
|
|
120
|
-
print(parse_schema(field))
|
|
140
|
+
# ➜ [('path', 'str',
|
|
141
|
+
# "The literal string 'C:\\Program Files\\My,App'")]
|
|
121
142
|
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
143
|
+
SAMPLE_8 = (
|
|
144
|
+
"transform: Callable[[int, str], bool] | Function that returns True on success,"
|
|
145
|
+
"retries: int | How many times to retry"
|
|
146
|
+
)
|
|
147
|
+
# ➜ ('transform', 'Callable[[int, str], bool]', 'Function that returns True on success')
|
|
148
|
+
# ('retries', 'int', 'How many times to retry')
|
|
149
|
+
|
|
150
|
+
SAMPLE_9 = (
|
|
151
|
+
r"regex: str | Pattern such as r'^[A-Z\|a-z]+$',"
|
|
152
|
+
"flags: int | re flags to use"
|
|
153
|
+
)
|
|
154
|
+
# ➜ ('regex', 'str', "Pattern such as r'^[A-Z\\|a-z]+$'")
|
|
155
|
+
# ('flags', 'int', 're flags to use')
|
|
156
|
+
|
|
157
|
+
SAMPLE_10 = "id:int, name:str," # note the final comma!
|
|
158
|
+
# ➜ ('id', 'int', '')
|
|
159
|
+
# ('name', 'str', '')
|
|
160
|
+
|
|
161
|
+
SAMPLE_11 = "id:int | Primary key\nname:str | Display name\nactive:bool"
|
|
162
|
+
# ➜ should not work!
|
|
163
|
+
|
|
164
|
+
SAMPLE_12 = (
|
|
165
|
+
'comment:str | The text "done | failed" goes here,'
|
|
166
|
+
'status:Literal["done","failed"]'
|
|
167
|
+
)
|
|
168
|
+
# ➜ ('comment', 'str', 'The text "done | failed" goes here')
|
|
169
|
+
# ('status', 'Literal["done","failed"]', '')
|
|
170
|
+
|
|
171
|
+
SAMPLE_13 = "choice: Literal['He said \\'yes\\'', 'no'] | User response"
|
|
172
|
+
# ➜ ('choice', "Literal['He said \\'yes\\'', 'no']", 'User response')
|
|
173
|
+
|
|
174
|
+
SAMPLE_14 = ""
|
|
175
|
+
# ➜ []
|
|
176
|
+
|
|
177
|
+
SAMPLE_15 = "username"
|
|
178
|
+
# ➜ [('username', 'str', '')]
|
|
179
|
+
|
|
180
|
+
SAMPLE_16 = (
|
|
181
|
+
"payload: dict[str, list[dict[str, tuple[int,str]]]] "
|
|
182
|
+
"| Arbitrarily complex structure"
|
|
183
|
+
)
|
|
184
|
+
# ➜ ('payload', 'dict[str, list[dict[str, tuple[int,str]]]]',
|
|
185
|
+
# 'Arbitrarily complex structure')
|
|
186
|
+
|
|
187
|
+
SAMPLE_17 = "münze: str | Deutsche Münzbezeichnung, engl. 'coin'"
|
|
188
|
+
# ➜ [('münze', 'str', "Deutsche Münzbezeichnung, engl. 'coin'")]
|
|
189
|
+
|
|
190
|
+
for title, spec in [
|
|
191
|
+
("Sample-1", SAMPLE_1),
|
|
192
|
+
("Sample-2", SAMPLE_2),
|
|
193
|
+
("Sample-3", SAMPLE_3),
|
|
194
|
+
("Sample-4", SAMPLE_4),
|
|
195
|
+
("Sample-5", SAMPLE_5),
|
|
196
|
+
("Sample-6", SAMPLE_6),
|
|
197
|
+
("Sample-7", SAMPLE_7),
|
|
198
|
+
("Sample-8", SAMPLE_8),
|
|
199
|
+
("Sample-9", SAMPLE_9),
|
|
200
|
+
("Sample-10", SAMPLE_10),
|
|
201
|
+
("Sample-11", SAMPLE_11),
|
|
202
|
+
("Sample-12", SAMPLE_12),
|
|
203
|
+
("Sample-13", SAMPLE_13),
|
|
204
|
+
("Sample-14", SAMPLE_14),
|
|
205
|
+
("Sample-15", SAMPLE_15),
|
|
206
|
+
("Sample-16", SAMPLE_16),
|
|
207
|
+
("Sample-17", SAMPLE_17),
|
|
208
|
+
]:
|
|
209
|
+
print(f"\n{title}")
|
|
210
|
+
for row in parse_schema(spec):
|
|
211
|
+
print(row)
|
|
@@ -20,10 +20,10 @@ flock/cli/yaml_editor.py,sha256=K3N0bh61G1TSDAZDnurqW9e_-hO6CtSQKXQqlDhCjVo,1252
|
|
|
20
20
|
flock/cli/assets/release_notes.md,sha256=bqnk50jxM3w5uY44Dc7MkdT8XmRREFxrVBAG9XCOSSU,4896
|
|
21
21
|
flock/core/__init__.py,sha256=p7lmQULRu9ejIAELfanZiyMhW0CougIPvyFHW2nqBFQ,847
|
|
22
22
|
flock/core/flock.py,sha256=_T_KAFePtEGDzfiFGV1HCdz7VHzj_U0cCquhAQ4xMAM,28199
|
|
23
|
-
flock/core/flock_agent.py,sha256=
|
|
23
|
+
flock/core/flock_agent.py,sha256=JTqaGD_OnZSd3bVU989WMsK1rAT6UGn-JYrPxFV15EE,39576
|
|
24
24
|
flock/core/flock_evaluator.py,sha256=dOXZeDOGZcAmJ9ahqq_2bdGUU1VOXY4skmwTVpAjiVw,1685
|
|
25
25
|
flock/core/flock_factory.py,sha256=_4zsjkEmJnCR7IvJ3SUHnDbX6c7Tt3E4P5ohxwKvE6w,3173
|
|
26
|
-
flock/core/flock_module.py,sha256=
|
|
26
|
+
flock/core/flock_module.py,sha256=UCK6TFe4viXs596zeng0GD3gln4ZNGu_gCWkXIIMREg,3090
|
|
27
27
|
flock/core/flock_registry.py,sha256=Qcu9juUFNyDAOEsqVxauwVlWdfgKZrSzc8yT8JMiK-c,24246
|
|
28
28
|
flock/core/flock_router.py,sha256=1OAXDsdaIIFApEfo6SRfFEDoTuGt3Si7n2MXiySEfis,2644
|
|
29
29
|
flock/core/api/__init__.py,sha256=OKlhzDWZJfA6ddBwxQUmATY0TSzESsH032u00iVGvdA,228
|
|
@@ -71,12 +71,12 @@ flock/core/tools/llm_tools.py,sha256=Bdt4Dpur5dGpxd2KFEQyxjfZazvW1HCDKY6ydMj6UgQ
|
|
|
71
71
|
flock/core/tools/markdown_tools.py,sha256=W6fGM48yGHbifVlaOk1jOtVcybfRbRmf20VbDOZv8S4,6031
|
|
72
72
|
flock/core/tools/zendesk_tools.py,sha256=deZAyUi9j-_yZaTayLQVJaFXIqIct-P6C8IGN5UU_tM,3528
|
|
73
73
|
flock/core/tools/dev_tools/github.py,sha256=a2OTPXS7kWOVA4zrZHynQDcsmEi4Pac5MfSjQOLePzA,5308
|
|
74
|
-
flock/core/util/cli_helper.py,sha256=
|
|
74
|
+
flock/core/util/cli_helper.py,sha256=g4u8kCtbwHRXETzBz1cw52_8muSWbWlr00CqST525jI,49963
|
|
75
75
|
flock/core/util/file_path_utils.py,sha256=Odf7uU32C-x1KNighbNERSiMtkzW4h8laABIoFK7A5M,6246
|
|
76
76
|
flock/core/util/hydrator.py,sha256=QJvCA8F4nkSP5akp3yg0cT6oaajOr1n7sldW5dCs6Lo,10733
|
|
77
77
|
flock/core/util/input_resolver.py,sha256=KPoPSpklyCoiR2t5r6J6GJHegmPLFZ0YE126VcKBewM,4703
|
|
78
78
|
flock/core/util/loader.py,sha256=j3q2qem5bFMP2SmMuYjb-ISxsNGNZd1baQmpvAnRUUk,2244
|
|
79
|
-
flock/core/util/spliter.py,sha256=
|
|
79
|
+
flock/core/util/spliter.py,sha256=D-P4u3vdKQFyC4DltpCoX4PExXuOKnE-G5kBG_6H678,6770
|
|
80
80
|
flock/evaluators/declarative/declarative_evaluator.py,sha256=q3qKHuKrj17mhaoOZuKh2HyVfiDBEEUk1Y1ZrejvggA,6328
|
|
81
81
|
flock/evaluators/memory/memory_evaluator.py,sha256=ySwz7kcc8suXMJ7gKNSWThW8iOMlE8lUcUzEAHvv8rw,3559
|
|
82
82
|
flock/evaluators/test/test_case_evaluator.py,sha256=3Emcoty0LOLLBIuPGxSpKphuZC9Fu1DTr1vbGg-hd0Q,1233
|
|
@@ -445,8 +445,8 @@ flock/workflow/agent_execution_activity.py,sha256=Gy6FtuVAjf0NiUXmC3syS2eJpNQF4R
|
|
|
445
445
|
flock/workflow/flock_workflow.py,sha256=iSUF_soFvWar0ffpkzE4irkDZRx0p4HnwmEBi_Ne2sY,9666
|
|
446
446
|
flock/workflow/temporal_config.py,sha256=3_8O7SDEjMsSMXsWJBfnb6XTp0TFaz39uyzSlMTSF_I,3988
|
|
447
447
|
flock/workflow/temporal_setup.py,sha256=YIHnSBntzOchHfMSh8hoLeNXrz3B1UbR14YrR6soM7A,1606
|
|
448
|
-
flock_core-0.4.
|
|
449
|
-
flock_core-0.4.
|
|
450
|
-
flock_core-0.4.
|
|
451
|
-
flock_core-0.4.
|
|
452
|
-
flock_core-0.4.
|
|
448
|
+
flock_core-0.4.0b34.dist-info/METADATA,sha256=xImOi53HupDqDi8RpnOjZfkS_rbLJQ6j_CrwoIR7RPA,17125
|
|
449
|
+
flock_core-0.4.0b34.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
|
450
|
+
flock_core-0.4.0b34.dist-info/entry_points.txt,sha256=rWaS5KSpkTmWySURGFZk6PhbJ87TmvcFQDi2uzjlagQ,37
|
|
451
|
+
flock_core-0.4.0b34.dist-info/licenses/LICENSE,sha256=iYEqWy0wjULzM9GAERaybP4LBiPeu7Z1NEliLUdJKSc,1072
|
|
452
|
+
flock_core-0.4.0b34.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|