flock-core 0.2.1__py3-none-any.whl → 0.2.3__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 +4 -0
- flock/config.py +29 -0
- flock/core/__init__.py +5 -0
- flock/core/context/context.py +104 -133
- flock/core/execution/temporal_executor.py +22 -6
- flock/core/flock.py +94 -62
- flock/core/flock_agent.py +150 -68
- flock/core/logging/logging.py +22 -4
- flock/core/logging/telemetry.py +109 -0
- flock/core/logging/telemetry_exporter/file_span.py +37 -0
- flock/core/logging/telemetry_exporter/sqllite_span.py +68 -0
- flock/core/logging/trace_and_logged.py +55 -0
- flock/core/mixin/dspy_integration.py +40 -14
- flock/core/registry/agent_registry.py +89 -74
- flock/core/tools/basic_tools.py +27 -4
- flock/core/tools/dev_tools/github.py +37 -8
- flock/core/util/cli_helper.py +7 -3
- flock/workflow/activities.py +148 -90
- {flock_core-0.2.1.dist-info → flock_core-0.2.3.dist-info}/METADATA +36 -2
- {flock_core-0.2.1.dist-info → flock_core-0.2.3.dist-info}/RECORD +22 -22
- flock/agents/__init__.py +0 -0
- flock/agents/batch_agent.py +0 -140
- flock/agents/loop_agent.py +0 -117
- flock/agents/trigger_agent.py +0 -113
- flock/agents/user_agent.py +0 -145
- {flock_core-0.2.1.dist-info → flock_core-0.2.3.dist-info}/WHEEL +0 -0
- {flock_core-0.2.1.dist-info → flock_core-0.2.3.dist-info}/licenses/LICENSE +0 -0
flock/agents/trigger_agent.py
DELETED
|
@@ -1,113 +0,0 @@
|
|
|
1
|
-
from collections.abc import Callable
|
|
2
|
-
from typing import Any
|
|
3
|
-
|
|
4
|
-
from pydantic import Field
|
|
5
|
-
|
|
6
|
-
from flock.core.context.context import FlockContext
|
|
7
|
-
from flock.core.flock_agent import FlockAgent
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
class TriggerAgent(FlockAgent):
|
|
11
|
-
"""An agent that executes based on specific triggers/conditions.
|
|
12
|
-
|
|
13
|
-
Attributes:
|
|
14
|
-
input: Input domain for the agent
|
|
15
|
-
output: Output types for the agent
|
|
16
|
-
tools: Tools the agent is allowed to use
|
|
17
|
-
trigger_condition: Callable that evaluates whether the agent should execute
|
|
18
|
-
trigger_check_interval: How often to check the trigger condition (in seconds)
|
|
19
|
-
max_wait_time: Maximum time to wait for trigger (in seconds)
|
|
20
|
-
"""
|
|
21
|
-
|
|
22
|
-
input: str = Field(default="", description="Input domain for the agent")
|
|
23
|
-
output: str = Field(default="", description="Output types for the agent")
|
|
24
|
-
tools: list[Callable] | None = Field(default=None, description="Tools the agent is allowed to use")
|
|
25
|
-
trigger_condition: Callable[[dict[str, Any]], bool] = Field(
|
|
26
|
-
..., description="Function that evaluates trigger conditions"
|
|
27
|
-
)
|
|
28
|
-
trigger_check_interval: float = Field(default=1.0, description="Interval between trigger checks (seconds)")
|
|
29
|
-
max_wait_time: float = Field(default=60.0, description="Maximum time to wait for trigger (seconds)")
|
|
30
|
-
|
|
31
|
-
async def _evaluate_trigger(self, context: FlockContext) -> bool:
|
|
32
|
-
"""Evaluate the trigger condition."""
|
|
33
|
-
try:
|
|
34
|
-
return self.trigger_condition(context.state)
|
|
35
|
-
except Exception:
|
|
36
|
-
raise
|
|
37
|
-
|
|
38
|
-
async def _execute_action(self, context: FlockContext) -> dict[str, Any]:
|
|
39
|
-
"""Execute the agent's action once triggered."""
|
|
40
|
-
try:
|
|
41
|
-
# Here you would implement the actual action logic
|
|
42
|
-
# For now, we'll just return a simple result
|
|
43
|
-
result = {"status": "completed", "trigger_time": context.state.get("current_time")}
|
|
44
|
-
return result
|
|
45
|
-
except Exception:
|
|
46
|
-
raise
|
|
47
|
-
|
|
48
|
-
async def run(self, context: FlockContext) -> dict[str, Any]:
|
|
49
|
-
"""Run the agent, waiting for and responding to triggers."""
|
|
50
|
-
import asyncio
|
|
51
|
-
import time
|
|
52
|
-
|
|
53
|
-
try:
|
|
54
|
-
start_time = time.time()
|
|
55
|
-
triggered = False
|
|
56
|
-
|
|
57
|
-
while (time.time() - start_time) < self.max_wait_time:
|
|
58
|
-
if await self._evaluate_trigger(context):
|
|
59
|
-
triggered = True
|
|
60
|
-
break
|
|
61
|
-
|
|
62
|
-
await asyncio.sleep(self.trigger_check_interval)
|
|
63
|
-
|
|
64
|
-
if not triggered:
|
|
65
|
-
return {"error": "Trigger timeout", "max_wait_time": self.max_wait_time}
|
|
66
|
-
|
|
67
|
-
# Execute action when triggered
|
|
68
|
-
result = await self._execute_action(context)
|
|
69
|
-
return result
|
|
70
|
-
|
|
71
|
-
except Exception:
|
|
72
|
-
raise
|
|
73
|
-
|
|
74
|
-
async def run_temporal(self, context: FlockContext) -> dict[str, Any]:
|
|
75
|
-
"""Run the trigger agent via Temporal."""
|
|
76
|
-
try:
|
|
77
|
-
from temporalio.client import Client
|
|
78
|
-
|
|
79
|
-
from flock.workflow.agent_activities import run_agent_activity
|
|
80
|
-
from flock.workflow.temporal_setup import run_activity
|
|
81
|
-
|
|
82
|
-
client = await Client.connect("localhost:7233", namespace="default")
|
|
83
|
-
|
|
84
|
-
# First activity: Monitor trigger
|
|
85
|
-
context_data = {
|
|
86
|
-
"state": context.state,
|
|
87
|
-
"history": [record.__dict__ for record in context.history],
|
|
88
|
-
"agent_definitions": [definition.__dict__ for definition in context.agent_definitions],
|
|
89
|
-
}
|
|
90
|
-
agent_data = self.dict()
|
|
91
|
-
|
|
92
|
-
monitor_result = await run_activity(
|
|
93
|
-
client,
|
|
94
|
-
f"{self.name}_monitor",
|
|
95
|
-
run_agent_activity,
|
|
96
|
-
{"agent_data": agent_data, "context_data": context_data},
|
|
97
|
-
)
|
|
98
|
-
|
|
99
|
-
if monitor_result.get("error"):
|
|
100
|
-
return monitor_result
|
|
101
|
-
|
|
102
|
-
# Second activity: Execute action
|
|
103
|
-
action_result = await run_activity(
|
|
104
|
-
client,
|
|
105
|
-
f"{self.name}_action",
|
|
106
|
-
run_agent_activity,
|
|
107
|
-
{"agent_data": agent_data, "context_data": context_data},
|
|
108
|
-
)
|
|
109
|
-
|
|
110
|
-
return action_result
|
|
111
|
-
|
|
112
|
-
except Exception:
|
|
113
|
-
raise
|
flock/agents/user_agent.py
DELETED
|
@@ -1,145 +0,0 @@
|
|
|
1
|
-
from collections.abc import Callable
|
|
2
|
-
from typing import Any
|
|
3
|
-
|
|
4
|
-
from pydantic import Field
|
|
5
|
-
from temporalio import activity
|
|
6
|
-
|
|
7
|
-
from flock.core.context.context import FlockContext
|
|
8
|
-
from flock.core.flock_agent import FlockAgent
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
@activity.defn
|
|
12
|
-
async def run_user_agent_activity(context: dict[str, Any]) -> dict[str, Any]:
|
|
13
|
-
"""Temporal activity to process a user agent task.
|
|
14
|
-
|
|
15
|
-
Expects context to contain:
|
|
16
|
-
- "model": the model name
|
|
17
|
-
- "agent_input": the key used for the input
|
|
18
|
-
- "output": the agent output specification
|
|
19
|
-
- "init_input": the initial input
|
|
20
|
-
- "tools": (optional) list of tools
|
|
21
|
-
"""
|
|
22
|
-
try:
|
|
23
|
-
import dspy
|
|
24
|
-
|
|
25
|
-
model = context.get("model")
|
|
26
|
-
agent_input = context.get("agent_input")
|
|
27
|
-
output = context.get("output")
|
|
28
|
-
init_input = context.get("init_input")
|
|
29
|
-
tools = context.get("tools")
|
|
30
|
-
|
|
31
|
-
lm = dspy.LM(model)
|
|
32
|
-
dspy.configure(lm=lm)
|
|
33
|
-
|
|
34
|
-
if tools:
|
|
35
|
-
agent_task = dspy.ReAct(f"{agent_input} -> {output}", tools=tools)
|
|
36
|
-
else:
|
|
37
|
-
agent_task = dspy.Predict(f"{agent_input} -> {output}")
|
|
38
|
-
|
|
39
|
-
kwargs = {agent_input: init_input}
|
|
40
|
-
result = agent_task(**kwargs).toDict()
|
|
41
|
-
result[agent_input] = init_input
|
|
42
|
-
|
|
43
|
-
return result
|
|
44
|
-
|
|
45
|
-
except Exception:
|
|
46
|
-
raise
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
class UserAgent(FlockAgent):
|
|
50
|
-
"""An agent that evaluates declarative inputs with user interaction capabilities.
|
|
51
|
-
|
|
52
|
-
This agent extends the base Agent class with the ability to interact with users
|
|
53
|
-
during execution, while maintaining compatibility with both local and Temporal
|
|
54
|
-
execution modes.
|
|
55
|
-
|
|
56
|
-
Attributes:
|
|
57
|
-
input: Input domain for the agent
|
|
58
|
-
output: Output types for the agent
|
|
59
|
-
tools: Tools the agent is allowed to use
|
|
60
|
-
require_confirmation: Whether to require user confirmation before proceeding
|
|
61
|
-
"""
|
|
62
|
-
|
|
63
|
-
input: str = Field(default="", description="Input domain for the agent")
|
|
64
|
-
output: str = Field(default="", description="Output types for the agent")
|
|
65
|
-
tools: list[Callable] | None = Field(default=None, description="Tools the agent is allowed to use")
|
|
66
|
-
require_confirmation: bool = Field(default=False, description="Whether to require user confirmation")
|
|
67
|
-
|
|
68
|
-
async def _configure_model(self) -> tuple[Any, Any]:
|
|
69
|
-
"""Configure the model and create the appropriate task."""
|
|
70
|
-
try:
|
|
71
|
-
import dspy
|
|
72
|
-
|
|
73
|
-
lm = dspy.LM(self.model)
|
|
74
|
-
dspy.configure(lm=lm)
|
|
75
|
-
|
|
76
|
-
if self.tools:
|
|
77
|
-
agent_task = dspy.ReAct(f"{self.input} -> {self.output}", tools=self.tools)
|
|
78
|
-
else:
|
|
79
|
-
agent_task = dspy.Predict(f"{self.input} -> {self.output}")
|
|
80
|
-
|
|
81
|
-
return lm, agent_task
|
|
82
|
-
|
|
83
|
-
except Exception:
|
|
84
|
-
raise
|
|
85
|
-
|
|
86
|
-
async def _execute_task(self, task: Any, context: FlockContext) -> dict[str, Any]:
|
|
87
|
-
"""Execute the configured task."""
|
|
88
|
-
try:
|
|
89
|
-
kwargs = {self.input: context.get_variable("init_input")}
|
|
90
|
-
result = task(**kwargs).toDict()
|
|
91
|
-
result[self.input] = kwargs[self.input]
|
|
92
|
-
return result
|
|
93
|
-
|
|
94
|
-
except Exception:
|
|
95
|
-
raise
|
|
96
|
-
|
|
97
|
-
async def run(self, context: FlockContext) -> dict[str, Any]:
|
|
98
|
-
"""Run the agent on a task with optional user interaction."""
|
|
99
|
-
try:
|
|
100
|
-
# Configure model and task
|
|
101
|
-
_, task = await self._configure_model()
|
|
102
|
-
|
|
103
|
-
# Execute with user confirmation if required
|
|
104
|
-
if self.require_confirmation:
|
|
105
|
-
# Here you would implement user confirmation logic
|
|
106
|
-
# For now, we'll just proceed
|
|
107
|
-
pass
|
|
108
|
-
|
|
109
|
-
# Execute the task
|
|
110
|
-
result = await self._execute_task(task, context)
|
|
111
|
-
return result
|
|
112
|
-
|
|
113
|
-
except Exception:
|
|
114
|
-
raise
|
|
115
|
-
|
|
116
|
-
async def run_temporal(self, context: FlockContext) -> dict[str, Any]:
|
|
117
|
-
"""Run the user agent via Temporal."""
|
|
118
|
-
try:
|
|
119
|
-
from temporalio.client import Client
|
|
120
|
-
|
|
121
|
-
from flock.workflow.temporal_setup import run_activity
|
|
122
|
-
|
|
123
|
-
client = await Client.connect("localhost:7233", namespace="default")
|
|
124
|
-
|
|
125
|
-
# Prepare context for temporal activity
|
|
126
|
-
activity_context = {
|
|
127
|
-
"model": self.model,
|
|
128
|
-
"agent_input": self.input,
|
|
129
|
-
"output": self.output,
|
|
130
|
-
"init_input": context.get_variable("init_input"),
|
|
131
|
-
"tools": self.tools,
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
# Execute the activity
|
|
135
|
-
result = await run_activity(
|
|
136
|
-
client,
|
|
137
|
-
self.name,
|
|
138
|
-
run_user_agent_activity,
|
|
139
|
-
activity_context,
|
|
140
|
-
)
|
|
141
|
-
|
|
142
|
-
return result
|
|
143
|
-
|
|
144
|
-
except Exception:
|
|
145
|
-
raise
|
|
File without changes
|
|
File without changes
|