flock-core 0.3.5__py3-none-any.whl → 0.3.8__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.

@@ -0,0 +1,363 @@
1
+ """LLM-based router implementation for the Flock framework."""
2
+
3
+ import json
4
+ from typing import Any
5
+
6
+ import litellm
7
+
8
+ from flock.core.context.context import FlockContext
9
+ from flock.core.flock_agent import FlockAgent
10
+ from flock.core.flock_router import (
11
+ FlockRouter,
12
+ FlockRouterConfig,
13
+ HandOffRequest,
14
+ )
15
+ from flock.core.logging.logging import get_logger
16
+
17
+ logger = get_logger("llm_router")
18
+
19
+
20
+ class LLMRouterConfig(FlockRouterConfig):
21
+ """Configuration for the LLM router.
22
+
23
+ This class extends FlockRouterConfig with parameters specific to the LLM router.
24
+ """
25
+
26
+ temperature: float = 0.2
27
+ max_tokens: int = 500
28
+ confidence_threshold: float = 0.5
29
+ prompt: str = ""
30
+
31
+
32
+ class LLMRouter(FlockRouter):
33
+ """Router that uses an LLM to determine the next agent in a workflow.
34
+
35
+ This class is responsible for:
36
+ 1. Analyzing available agents in the registry
37
+ 2. Using an LLM to score each agent's suitability as the next step
38
+ 3. Selecting the highest-scoring agent
39
+ 4. Creating a HandOff object with the selected agent
40
+ """
41
+
42
+ def __init__(
43
+ self,
44
+ name: str = "llm_router",
45
+ config: LLMRouterConfig | None = None,
46
+ ):
47
+ """Initialize the LLMRouter.
48
+
49
+ Args:
50
+ registry: The agent registry containing all available agents
51
+ name: The name of the router
52
+ config: The router configuration
53
+ """
54
+ logger.info(f"Initializing LLM Router '{name}'")
55
+ super().__init__(name=name, config=config or LLMRouterConfig(name=name))
56
+ logger.debug(
57
+ "LLM Router configuration",
58
+ temperature=self.config.temperature,
59
+ max_tokens=self.config.max_tokens,
60
+ )
61
+
62
+ async def route(
63
+ self,
64
+ current_agent: FlockAgent,
65
+ result: dict[str, Any],
66
+ context: FlockContext,
67
+ ) -> HandOffRequest:
68
+ """Determine the next agent to hand off to based on the current agent's output.
69
+
70
+ Args:
71
+ current_agent: The agent that just completed execution
72
+ result: The output from the current agent
73
+ context: The global execution context
74
+
75
+ Returns:
76
+ A HandOff object containing the next agent and input data
77
+ """
78
+ logger.info(
79
+ f"Routing from agent '{current_agent.name}'",
80
+ current_agent=current_agent.name,
81
+ )
82
+ logger.debug("Current agent result", result=result)
83
+
84
+ agent_definitions = context.agent_definitions
85
+ # Get all available agents from the registry
86
+ available_agents = self._get_available_agents(
87
+ agent_definitions, current_agent.name
88
+ )
89
+ logger.debug(
90
+ "Available agents for routing",
91
+ count=len(available_agents),
92
+ agents=[a.agent_data["name"] for a in available_agents],
93
+ )
94
+
95
+ if not available_agents:
96
+ logger.warning(
97
+ "No available agents for routing",
98
+ current_agent=current_agent.name,
99
+ )
100
+ return HandOffRequest(
101
+ next_agent="", override_next_agent={}, override_context=None
102
+ )
103
+
104
+ # Use LLM to determine the best next agent
105
+ next_agent_name, score = await self._select_next_agent(
106
+ current_agent, result, available_agents
107
+ )
108
+ logger.info(
109
+ "Agent selection result",
110
+ next_agent=next_agent_name,
111
+ score=score,
112
+ )
113
+
114
+ if not next_agent_name or score < self.config.confidence_threshold:
115
+ logger.warning(
116
+ "No suitable next agent found",
117
+ best_score=score,
118
+ )
119
+ return HandOffRequest(
120
+ next_agent="", override_next_agent={}, override_context=None
121
+ )
122
+
123
+ # Get the next agent from the registry
124
+ next_agent = agent_definitions.get(next_agent_name)
125
+ if not next_agent:
126
+ logger.error(
127
+ "Selected agent not found in registry",
128
+ agent_name=next_agent_name,
129
+ )
130
+ return HandOffRequest(
131
+ next_agent="", override_next_agent={}, override_context=None
132
+ )
133
+
134
+ # Create input for the next agent
135
+
136
+ logger.success(
137
+ f"Successfully routed to agent '{next_agent_name}'",
138
+ score=score,
139
+ from_agent=current_agent.name,
140
+ )
141
+ return HandOffRequest(
142
+ next_agent=next_agent_name,
143
+ hand_off_mode="add",
144
+ override_next_agent=None,
145
+ override_context=None,
146
+ )
147
+
148
+ def _get_available_agents(
149
+ self, agent_definitions: dict[str, Any], current_agent_name: str
150
+ ) -> list[FlockAgent]:
151
+ """Get all available agents except the current one.
152
+
153
+ Args:
154
+ current_agent_name: Name of the current agent to exclude
155
+
156
+ Returns:
157
+ List of available agents
158
+ """
159
+ logger.debug(
160
+ "Getting available agents",
161
+ total_agents=len(agent_definitions),
162
+ current_agent=current_agent_name,
163
+ )
164
+ agents = []
165
+ for agent in agent_definitions:
166
+ if agent != current_agent_name:
167
+ agents.append(agent_definitions.get(agent))
168
+ return agents
169
+
170
+ async def _select_next_agent(
171
+ self,
172
+ current_agent: FlockAgent,
173
+ result: dict[str, Any],
174
+ available_agents: list[FlockAgent],
175
+ ) -> tuple[str, float]:
176
+ """Use an LLM to select the best next agent.
177
+
178
+ Args:
179
+ current_agent: The agent that just completed execution
180
+ result: The output from the current agent
181
+ available_agents: List of available agents to choose from
182
+
183
+ Returns:
184
+ Tuple of (selected_agent_name, confidence_score)
185
+ """
186
+ logger.debug(
187
+ "Selecting next agent",
188
+ current_agent=current_agent.name,
189
+ available_count=len(available_agents),
190
+ )
191
+
192
+ # Prepare the prompt for the LLM
193
+ prompt = self._create_selection_prompt(
194
+ current_agent, result, available_agents
195
+ )
196
+ logger.debug("Generated selection prompt", prompt_length=len(prompt))
197
+
198
+ try:
199
+ logger.info(
200
+ "Calling LLM for agent selection",
201
+ model=current_agent.model,
202
+ temperature=self.config.temperature,
203
+ )
204
+ # Call the LLM to get the next agent
205
+ response = await litellm.acompletion(
206
+ model=current_agent.model,
207
+ messages=[{"role": "user", "content": prompt}],
208
+ temperature=self.config.temperature
209
+ if isinstance(self.config, LLMRouterConfig)
210
+ else 0.2,
211
+ max_tokens=self.config.max_tokens
212
+ if isinstance(self.config, LLMRouterConfig)
213
+ else 500,
214
+ )
215
+
216
+ content = response.choices[0].message.content
217
+ # Parse the response to get the agent name and score
218
+ try:
219
+ # extract the json object from the response
220
+ content = content.split("```json")[1].split("```")[0]
221
+ data = json.loads(content)
222
+ next_agent = data.get("next_agent", "")
223
+ score = float(data.get("score", 0))
224
+ reasoning = data.get("reasoning", "")
225
+ logger.info(
226
+ "Successfully parsed LLM response",
227
+ next_agent=next_agent,
228
+ score=score,
229
+ reasoning=reasoning,
230
+ )
231
+ return next_agent, score
232
+ except (json.JSONDecodeError, ValueError) as e:
233
+ logger.error(
234
+ "Failed to parse LLM response",
235
+ error=str(e),
236
+ raw_response=content,
237
+ )
238
+ logger.debug("Attempting fallback parsing")
239
+
240
+ # Fallback: try to extract the agent name from the text
241
+ for agent in available_agents:
242
+ if agent.agent_data["name"] in content:
243
+ logger.info(
244
+ "Found agent name in response using fallback",
245
+ agent=agent.agent_data["name"],
246
+ )
247
+ return agent.agent_data[
248
+ "name"
249
+ ], 0.6 # Default score for fallback
250
+
251
+ return "", 0.0
252
+
253
+ except Exception as e:
254
+ logger.error(
255
+ "Error calling LLM for agent selection",
256
+ error=str(e),
257
+ current_agent=current_agent.name,
258
+ )
259
+ return "", 0.0
260
+
261
+ def _create_selection_prompt(
262
+ self,
263
+ current_agent: FlockAgent,
264
+ result: dict[str, Any],
265
+ available_agents: list[FlockAgent],
266
+ ) -> str:
267
+ """Create a prompt for the LLM to select the next agent.
268
+
269
+ Args:
270
+ current_agent: The agent that just completed execution
271
+ result: The output from the current agent
272
+ available_agents: List of available agents to choose from
273
+
274
+ Returns:
275
+ Prompt string for the LLM
276
+ """
277
+ # Format the current agent's output
278
+ result_str = json.dumps(result, indent=2)
279
+
280
+ # Format the available agents' information
281
+ agents_info = []
282
+ for agent in available_agents:
283
+ agent_info = {
284
+ "name": agent.agent_data["name"],
285
+ "description": agent.agent_data["description"]
286
+ if agent.agent_data["description"]
287
+ else "",
288
+ "input": agent.agent_data["input"],
289
+ "output": agent.agent_data["output"],
290
+ }
291
+ agents_info.append(agent_info)
292
+
293
+ agents_str = json.dumps(agents_info, indent=2)
294
+
295
+ # Create the prompt
296
+ if self.config.prompt:
297
+ prompt = self.config.prompt
298
+ else:
299
+ prompt = f"""
300
+ You are a workflow router that determines the next agent to execute in a multi-agent system.
301
+
302
+ CURRENT AGENT:
303
+ Name: {current_agent.name}
304
+ Description: {current_agent.description}
305
+ Input: {current_agent.input}
306
+ Output: {current_agent.output}
307
+
308
+ CURRENT AGENT'S OUTPUT:
309
+ {result_str}
310
+
311
+ AVAILABLE AGENTS:
312
+ {agents_str}
313
+
314
+ Based on the current agent's output and the available agents, determine which agent should be executed next.
315
+ Consider the following:
316
+ 1. Which agent's input requirements best match the current agent's output?
317
+ 2. Which agent's purpose and description make it the most logical next step?
318
+ 3. Which agent would provide the most value in continuing the workflow?
319
+
320
+ Respond with a JSON object containing:
321
+ 1. "next_agent": The name of the selected agent
322
+ 2. "score": A confidence score between 0 and 1 indicating how suitable this agent is
323
+ 3. "reasoning": A brief explanation of why this agent was selected
324
+
325
+ If no agent is suitable, set "next_agent" to an empty string and "score" to 0.
326
+
327
+ JSON Response:
328
+ """
329
+ return prompt
330
+
331
+ def _create_next_input(
332
+ self,
333
+ current_agent: FlockAgent,
334
+ result: dict[str, Any],
335
+ next_agent: FlockAgent,
336
+ ) -> dict[str, Any]:
337
+ """Create the input for the next agent, including the previous agent's output.
338
+
339
+ Args:
340
+ current_agent: The agent that just completed execution
341
+ result: The output from the current agent
342
+ next_agent: The next agent to execute
343
+
344
+ Returns:
345
+ Input dictionary for the next agent
346
+ """
347
+ # Start with an empty input
348
+ next_input = {}
349
+
350
+ # Add a special field for the previous agent's output
351
+ next_input["previous_agent_output"] = {
352
+ "agent_name": current_agent.name,
353
+ "result": result,
354
+ }
355
+
356
+ # Try to map the current agent's output to the next agent's input
357
+ # This is a simple implementation that could be enhanced with more sophisticated mapping
358
+ for key in result:
359
+ # If the next agent expects this key, add it directly
360
+ if key in next_agent.input:
361
+ next_input[key] = result[key]
362
+
363
+ return next_input
@@ -7,7 +7,8 @@ from temporalio import activity
7
7
 
8
8
  from flock.core.context.context import FlockContext
9
9
  from flock.core.context.context_vars import FLOCK_CURRENT_AGENT
10
- from flock.core.flock_agent import FlockAgent, HandOff
10
+ from flock.core.flock_agent import FlockAgent
11
+ from flock.core.flock_router import HandOffRequest
11
12
  from flock.core.logging.logging import get_logger
12
13
  from flock.core.registry.agent_registry import Registry
13
14
  from flock.core.util.input_resolver import resolve_inputs
@@ -74,49 +75,83 @@ async def run_agent(context: FlockContext) -> dict:
74
75
  exec_span.record_exception(e)
75
76
  raise
76
77
 
77
- # If there is no handoff, record the result and finish.
78
- if not agent.hand_off:
79
- context.record(
80
- agent.name,
81
- result,
82
- timestamp=datetime.now().isoformat(),
83
- hand_off=None,
84
- called_from=previous_agent_name,
85
- )
78
+ # Determine the next agent using the handoff router if available
79
+ handoff_data = HandOffRequest()
80
+
81
+ if agent.handoff_router:
86
82
  logger.info(
87
- "No handoff defined, completing chain", agent=agent.name
83
+ f"Using handoff router: {agent.handoff_router.__class__.__name__}",
84
+ agent=agent.name,
88
85
  )
89
- iter_span.add_event("chain completed")
90
- return result
91
-
92
- # Determine the next agent.
93
- handoff_data = HandOff()
94
- if callable(agent.hand_off):
95
- logger.debug("Executing handoff function", agent=agent.name)
96
86
  try:
97
- handoff_data = agent.hand_off(context, result)
98
- if isinstance(handoff_data.next_agent, FlockAgent):
87
+ # Route to the next agent
88
+ handoff_data = await agent.handoff_router.route(
89
+ agent, result, context
90
+ )
91
+
92
+ if callable(handoff_data):
93
+ logger.debug(
94
+ "Executing handoff function", agent=agent.name
95
+ )
96
+ try:
97
+ handoff_data = handoff_data(context, result)
98
+ if isinstance(
99
+ handoff_data.next_agent, FlockAgent
100
+ ):
101
+ handoff_data.next_agent = (
102
+ handoff_data.next_agent.name
103
+ )
104
+ except Exception as e:
105
+ logger.error(
106
+ "Handoff function error {} {}",
107
+ agent=agent.name,
108
+ error=str(e),
109
+ )
110
+ iter_span.record_exception(e)
111
+ return {"error": f"Handoff function error: {e}"}
112
+ elif isinstance(handoff_data.next_agent, FlockAgent):
99
113
  handoff_data.next_agent = (
100
114
  handoff_data.next_agent.name
101
115
  )
116
+
117
+ if not handoff_data.next_agent:
118
+ logger.info(
119
+ "Router found no suitable next agent",
120
+ agent=agent.name,
121
+ )
122
+ context.record(
123
+ agent.name,
124
+ result,
125
+ timestamp=datetime.now().isoformat(),
126
+ hand_off=None,
127
+ called_from=previous_agent_name,
128
+ )
129
+ logger.info("Completing chain", agent=agent.name)
130
+ iter_span.add_event("chain completed")
131
+ return result
102
132
  except Exception as e:
103
133
  logger.error(
104
- "Handoff function error",
105
- agent=agent.name,
106
- error=str(e),
134
+ "Router error {} {}",
135
+ agent.name,
136
+ str(e),
107
137
  )
108
138
  iter_span.record_exception(e)
109
- return {"error": f"Handoff function error: {e}"}
110
- elif isinstance(agent.hand_off, str | FlockAgent):
111
- handoff_data.next_agent = (
112
- agent.hand_off
113
- if isinstance(agent.hand_off, str)
114
- else agent.hand_off.name
115
- )
139
+ return {"error": f"Router error: {e}"}
116
140
  else:
117
- logger.error("Unsupported hand_off type", agent=agent.name)
118
- iter_span.add_event("unsupported hand_off type")
119
- return {"error": "Unsupported hand_off type."}
141
+ # No router, so no handoff
142
+ logger.info(
143
+ "No handoff router defined, completing chain",
144
+ agent=agent.name,
145
+ )
146
+ context.record(
147
+ agent.name,
148
+ result,
149
+ timestamp=datetime.now().isoformat(),
150
+ hand_off=None,
151
+ called_from=previous_agent_name,
152
+ )
153
+ iter_span.add_event("chain completed")
154
+ return result
120
155
 
121
156
  # Record the agent run in the context.
122
157
  context.record(
@@ -127,10 +162,15 @@ async def run_agent(context: FlockContext) -> dict:
127
162
  called_from=previous_agent_name,
128
163
  )
129
164
  previous_agent_name = agent.name
165
+ previous_agent_output = agent.output
166
+ if handoff_data.override_context:
167
+ context.update(handoff_data.override_context)
130
168
 
131
169
  # Prepare the next agent.
132
170
  try:
133
171
  agent = registry.get_agent(handoff_data.next_agent)
172
+ if handoff_data.hand_off_mode == "add":
173
+ agent.input = previous_agent_output + ", " + agent.input
134
174
  agent.resolve_callables(context=context)
135
175
  if not agent:
136
176
  logger.error(
@@ -147,6 +187,7 @@ async def run_agent(context: FlockContext) -> dict:
147
187
  }
148
188
 
149
189
  context.set_variable(FLOCK_CURRENT_AGENT, agent.name)
190
+
150
191
  logger.info("Handing off to next agent", next=agent.name)
151
192
  iter_span.set_attribute("next.agent", agent.name)
152
193
  except Exception as e:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: flock-core
3
- Version: 0.3.5
3
+ Version: 0.3.8
4
4
  Summary: Declarative LLM Orchestration at Scale
5
5
  Author-email: Andre Ratzenberger <andre.ratzenberger@whiteduck.de>
6
6
  License-File: LICENSE
@@ -8,15 +8,16 @@ flock/cli/load_examples.py,sha256=DkeLUlrb7rGx3nZ04aADU9HXXu5mZTf_DBwT0xhzIv4,7
8
8
  flock/cli/load_flock.py,sha256=3JdECvt5X7uyOG2vZS3-Zk5C5SI_84_QZjcsB3oJmfA,932
9
9
  flock/cli/load_release_notes.py,sha256=qFcgUrMddAE_TP6x1P-6ZywTUjTknfhTDW5LTxtg1yk,599
10
10
  flock/cli/settings.py,sha256=DkeLUlrb7rGx3nZ04aADU9HXXu5mZTf_DBwT0xhzIv4,7
11
- flock/cli/assets/release_notes.md,sha256=K-upUm5vuUuRSSU2FkMdgDfai_YlDk_vTCp0s4s2WO0,3419
11
+ flock/cli/assets/release_notes.md,sha256=-RuE-G9Sn8z1LWEdr9iqjuQN7N1K_JMaCzHYoyLR42U,4793
12
12
  flock/core/__init__.py,sha256=mPlvKc0SxC2qCvSlgYeP_7EyV8ptmdn24NO8mlQoCSo,559
13
13
  flock/core/flock.py,sha256=1LPMblsvT90Na35LXx0w3Us66yIaTzsokL7lF5fsVX8,19228
14
- flock/core/flock_agent.py,sha256=RzKX0GRrRJz16YbQFheMo8TqJPXOZSHWNloTbp35zwI,12229
14
+ flock/core/flock_agent.py,sha256=LjSuAYRFh4UWV8Z4_mguMme2GnMQwteNFyion4Memt8,11705
15
15
  flock/core/flock_api.py,sha256=SKQVKgFCaNCqHtwvIcksnpqG6ajHodVhs3oaKUw-d8c,7192
16
16
  flock/core/flock_evaluator.py,sha256=j7riJj_KsWoBnKmLiGp-U0CRhxDyJbgEdLGN26tfKm8,1588
17
- flock/core/flock_factory.py,sha256=vyDq0eyFT4MyE_n2JyNU7YaFx2ljmjSDmZ07OIsmIOE,2694
18
- flock/core/flock_module.py,sha256=VWFlBiY2RHZLTlGYfcchuT41M3m_JrZcmzw07u7KayM,2581
19
- flock/core/context/context.py,sha256=fb7SsGAXmhQ1CvHV3_GihGiJG-4oLJ_DcexJ8vsrbHM,6371
17
+ flock/core/flock_factory.py,sha256=xTz2VqcLjaHn60b3Oaz8JCJdcIQra0vc5NHqh3Dy44s,2617
18
+ flock/core/flock_module.py,sha256=3DmxOc39gQS-tiJcgUCjMaLr8QDDJR4acV_M76Xcf6I,2602
19
+ flock/core/flock_router.py,sha256=A5GaxcGvtiFlRLHBTW7okh5RDm3BdKam2uXvRHRaj7k,2187
20
+ flock/core/context/context.py,sha256=AW0qKIAkgZucVroGsulrPVPc4WmWuqWIrVPHf2qaOLI,6380
20
21
  flock/core/context/context_manager.py,sha256=qMySVny_dbTNLh21RHK_YT0mNKIOrqJDZpi9ZVdBsxU,1103
21
22
  flock/core/context/context_vars.py,sha256=0Hn6fM2iNc0_jIIU0B7KX-K2o8qXqtZ5EYtwujETQ7U,272
22
23
  flock/core/execution/local_executor.py,sha256=rnIQvaJOs6zZORUcR3vvyS6LPREDJTjaygl_Db0M8ao,952
@@ -37,15 +38,16 @@ flock/core/logging/telemetry_exporter/sqlite_exporter.py,sha256=CDsiMb9QcqeXelZ6
37
38
  flock/core/mixin/dspy_integration.py,sha256=P5G4Y04nl5hFwFbJXCkQ-0TMR1L4skLL2IM_FlUjH_c,8364
38
39
  flock/core/mixin/prompt_parser.py,sha256=eOqI-FK3y17gVqpc_y5GF-WmK1Jv8mFlkZxTcgweoxI,5121
39
40
  flock/core/registry/agent_registry.py,sha256=TUClh9e3eA6YzZC1CMTlsTPvQeqb9jYHewi-zPpcWM8,4987
41
+ flock/core/serialization/secure_serializer.py,sha256=n5-zRvvXddgJv1FFHsaQ2wuYdL3WUSGPvG_LGaffEJo,6144
42
+ flock/core/serialization/serializable.py,sha256=SymJ0YrjBx48mOBItYSqoRpKuzIc4vKWRS6ScTzre7s,2573
40
43
  flock/core/tools/basic_tools.py,sha256=fI9r81_ktRiRhNLwT-jSJ9rkjl28LC1ZfL-njnno2iw,4761
41
44
  flock/core/tools/dev_tools/github.py,sha256=a2OTPXS7kWOVA4zrZHynQDcsmEi4Pac5MfSjQOLePzA,5308
42
45
  flock/core/util/cli_helper.py,sha256=IOl9r4cz_MJv_Bp5R8dhHX8f-unAqA9vDS6-0E90Vzk,49813
43
46
  flock/core/util/hydrator.py,sha256=6qNwOwCZB7r6y25BZ--0PGofrAlfMaXbDKFQeP5NLts,11196
44
47
  flock/core/util/input_resolver.py,sha256=g9vDPdY4OH-G7qjas5ksGEHueokHGFPMoLOvC-ngeLo,5984
45
- flock/core/util/serializable.py,sha256=SymJ0YrjBx48mOBItYSqoRpKuzIc4vKWRS6ScTzre7s,2573
46
48
  flock/evaluators/declarative/declarative_evaluator.py,sha256=f8ldgZZp94zC4CoGzBufKvbvtckCGBe9EHTOoAZfZK0,1695
47
49
  flock/evaluators/natural_language/natural_language_evaluator.py,sha256=6nVEeh8_uwv_h-d3FWlA0GbzDzRtdhvxCGKirHtyvOU,2012
48
- flock/evaluators/zep/zep_evaluator.py,sha256=hEHQdgIwGsbC4ci9RvtdA2k7f4M0yznIok4v4XltNwg,1885
50
+ flock/evaluators/zep/zep_evaluator.py,sha256=9NOELl7JAuUcx_FQrxY6b-_vN3MjwDyW7ZppPIGeCFc,1954
49
51
  flock/modules/callback/callback_module.py,sha256=hCCw-HNYjK4aHnUQfvw26ZP1Q_jdlKb9kDh3BHzbCQA,2916
50
52
  flock/modules/memory/memory_module.py,sha256=2grdmvw7FJWZvz0IjgASbDPCfyS1w4gWkRzOWtK7BFM,8214
51
53
  flock/modules/memory/memory_parser.py,sha256=2S7CmVEsm22gD7-MiFj4318FTg8wd_jB-RKMwXI14WM,4369
@@ -55,6 +57,14 @@ flock/modules/performance/metrics_module.py,sha256=K5z5bizIjA4ZEUjBk5ShwTR9ZElR-
55
57
  flock/modules/zep/zep_module.py,sha256=BIJ5K-hg2bLeJmGKoDcVY1rVN7_0yYETiSaVrO-gtMI,5830
56
58
  flock/platform/docker_tools.py,sha256=fpA7-6rJBjPOUBLdQP4ny2QPgJ_042nmqRn5GtKnoYw,1445
57
59
  flock/platform/jaeger_install.py,sha256=MyOMJQx4TQSMYvdUJxfiGSo3YCtsfkbNXcAcQ9bjETA,2898
60
+ flock/routers/__init__.py,sha256=w9uL34Auuo26-q_EGlE8Z9iHsw6S8qutTAH_ZI7pn7M,39
61
+ flock/routers/agent/__init__.py,sha256=0ZOYpR8BMnR5iCGfcUiv99g7aT_g13xvm2Shl-XzybY,65
62
+ flock/routers/agent/agent_router.py,sha256=9s3AwcBqpyhpPXOTqyMSVtS8Bcme1RDdqSUfWIqEBfc,8139
63
+ flock/routers/agent/handoff_agent.py,sha256=p-0XEPXIyv1T3DGAhhXg2SYXmrwEaJ5pnuLgRSvbiZg,1903
64
+ flock/routers/default/__init__.py,sha256=DOatGX_aE2DWvf55a0Tv7qDK05QFD-hL3sm7g58hmLU,61
65
+ flock/routers/default/default_router.py,sha256=D9TCAAeNfzt3Se6QduGO2TmZ6038XlQLV6Y1u5IGI-0,2232
66
+ flock/routers/llm/__init__.py,sha256=OV89ebq8RPWZwCJTS2_P46Q0yKD_03rwq_fBOsETd08,63
67
+ flock/routers/llm/llm_router.py,sha256=3WXUK2TqZENYXSFb7o_WtpONq0SsebaZZpytCRr1daw,12217
58
68
  flock/themes/3024-day.toml,sha256=uOVHqEzSyHx0WlUk3D0lne4RBsNBAPCTy3C58yU7kEY,667
59
69
  flock/themes/3024-night.toml,sha256=qsXUwd6ZYz6J-R129_Ao2TKlvvK60svhZJJjB5c8Tfo,1667
60
70
  flock/themes/aardvark-blue.toml,sha256=5ZgsxP3pWLPN3yJ2Wd9ErCo7fy_VJpIfje4kriDKlqo,1667
@@ -392,12 +402,12 @@ flock/themes/zenburned.toml,sha256=UEmquBbcAO3Zj652XKUwCsNoC2iQSlIh-q5c6DH-7Kc,1
392
402
  flock/themes/zenwritten-dark.toml,sha256=To5l6520_3UqAGiEumpzGWsHhXxqu9ThrMildXKgIO0,1669
393
403
  flock/themes/zenwritten-light.toml,sha256=G1iEheCPfBNsMTGaVpEVpDzYBHA_T-MV27rolUYolmE,1666
394
404
  flock/workflow/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
395
- flock/workflow/activities.py,sha256=2zcYyDoCuYs9oQbnhLjCzBUdEi7d5IEIemKJ7TV_B8w,6932
405
+ flock/workflow/activities.py,sha256=PqUc1jecg-7qq4KQr0Gr2XLNCABZ79fvD1MqazT--YU,8866
396
406
  flock/workflow/agent_activities.py,sha256=NhBZscflEf2IMfSRa_pBM_TRP7uVEF_O0ROvWZ33eDc,963
397
407
  flock/workflow/temporal_setup.py,sha256=VWBgmBgfTBjwM5ruS_dVpA5AVxx6EZ7oFPGw4j3m0l0,1091
398
408
  flock/workflow/workflow.py,sha256=I9MryXW_bqYVTHx-nl2epbTqeRy27CAWHHA7ZZA0nAk,1696
399
- flock_core-0.3.5.dist-info/METADATA,sha256=MBhu8EjW-aFe1MCkusE0AiL4tE7Pv6kdh1czCCbqVLU,20494
400
- flock_core-0.3.5.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
401
- flock_core-0.3.5.dist-info/entry_points.txt,sha256=rWaS5KSpkTmWySURGFZk6PhbJ87TmvcFQDi2uzjlagQ,37
402
- flock_core-0.3.5.dist-info/licenses/LICENSE,sha256=iYEqWy0wjULzM9GAERaybP4LBiPeu7Z1NEliLUdJKSc,1072
403
- flock_core-0.3.5.dist-info/RECORD,,
409
+ flock_core-0.3.8.dist-info/METADATA,sha256=0ImaV46N5uSNlZPP4kF2q-pjfY3nsLLHzDvicvv7_gA,20494
410
+ flock_core-0.3.8.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
411
+ flock_core-0.3.8.dist-info/entry_points.txt,sha256=rWaS5KSpkTmWySURGFZk6PhbJ87TmvcFQDi2uzjlagQ,37
412
+ flock_core-0.3.8.dist-info/licenses/LICENSE,sha256=iYEqWy0wjULzM9GAERaybP4LBiPeu7Z1NEliLUdJKSc,1072
413
+ flock_core-0.3.8.dist-info/RECORD,,
File without changes