flock-core 0.1.2__py3-none-any.whl → 0.2.2__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 +1 -4
- flock/core/__init__.py +1 -7
- flock/core/context/context.py +182 -0
- flock/core/context/context_manager.py +34 -0
- flock/core/{context_vars.py → context/context_vars.py} +8 -6
- flock/core/execution/local_executor.py +27 -0
- flock/core/execution/temporal_executor.py +56 -0
- flock/core/flock.py +232 -208
- flock/core/flock_agent.py +574 -0
- flock/core/logging/__init__.py +2 -18
- flock/core/logging/formatters/base_formatter.py +36 -0
- flock/core/logging/formatters/formatter_factory.py +38 -0
- flock/core/logging/formatters/pprint_formatter.py +18 -0
- flock/core/logging/formatters/rich_formatters.py +132 -0
- flock/core/logging/formatters/theme_builder.py +480 -0
- flock/core/logging/formatters/themed_formatter.py +442 -0
- flock/core/logging/logging.py +141 -0
- flock/core/logging/telemetry.py +21 -0
- flock/core/logging/trace_and_logged.py +55 -0
- flock/core/mixin/dspy_integration.py +197 -0
- flock/core/mixin/prompt_parser.py +125 -0
- flock/core/registry/agent_registry.py +118 -0
- flock/core/tools/basic_tools.py +296 -98
- flock/core/tools/dev_tools/github.py +190 -0
- flock/core/util/cli_helper.py +25 -0
- flock/core/util/input_resolver.py +156 -0
- flock/core/util/serializable.py +93 -0
- flock/themes/3024-day.toml +39 -0
- flock/themes/3024-night.toml +77 -0
- flock/themes/aardvark-blue.toml +77 -0
- flock/themes/abernathy.toml +77 -0
- flock/themes/adventure.toml +77 -0
- flock/themes/adventuretime.toml +77 -0
- flock/themes/afterglow.toml +77 -0
- flock/themes/alabaster.toml +77 -0
- flock/themes/alienblood.toml +77 -0
- flock/themes/andromeda.toml +77 -0
- flock/themes/apple-classic.toml +77 -0
- flock/themes/apple-system-colors.toml +77 -0
- flock/themes/arcoiris.toml +77 -0
- flock/themes/argonaut copy.toml +77 -0
- flock/themes/argonaut.toml +39 -0
- flock/themes/arthur.toml +77 -0
- flock/themes/ateliersulphurpool.toml +77 -0
- flock/themes/atom.toml +38 -0
- flock/themes/atom_test.toml +65 -0
- flock/themes/atomonelight.toml +77 -0
- flock/themes/aurora.toml +77 -0
- flock/themes/ayu copy.toml +77 -0
- flock/themes/ayu-light.toml +77 -0
- flock/themes/ayu-mirage.toml +77 -0
- flock/themes/ayu.toml +39 -0
- flock/themes/banana-blueberry.toml +77 -0
- flock/themes/batman.toml +77 -0
- flock/themes/belafonte-day.toml +77 -0
- flock/themes/belafonte-night.toml +77 -0
- flock/themes/birdsofparadise.toml +77 -0
- flock/themes/blazer.toml +77 -0
- flock/themes/blue-matrix.toml +77 -0
- flock/themes/blueberrypie.toml +77 -0
- flock/themes/bluedolphin.toml +77 -0
- flock/themes/blulocodark.toml +77 -0
- flock/themes/blulocolight.toml +77 -0
- flock/themes/borland.toml +77 -0
- flock/themes/breeze.toml +77 -0
- flock/themes/bright-lights.toml +77 -0
- flock/themes/broadcast.toml +77 -0
- flock/themes/brogrammer.toml +77 -0
- flock/themes/builtin-dark.toml +77 -0
- flock/themes/builtin-light.toml +77 -0
- flock/themes/builtin-pastel-dark.toml +77 -0
- flock/themes/builtin-solarized-dark.toml +77 -0
- flock/themes/builtin-solarized-light.toml +77 -0
- flock/themes/builtin-tango-dark.toml +77 -0
- flock/themes/builtin-tango-light.toml +77 -0
- flock/themes/c64.toml +77 -0
- flock/themes/calamity.toml +77 -0
- flock/themes/catppuccin-frappe.toml +77 -0
- flock/themes/catppuccin-latte.toml +77 -0
- flock/themes/catppuccin-macchiato.toml +77 -0
- flock/themes/catppuccin-mocha.toml +77 -0
- flock/themes/cga.toml +77 -0
- flock/themes/chalk.toml +77 -0
- flock/themes/chalkboard.toml +77 -0
- flock/themes/challengerdeep.toml +77 -0
- flock/themes/chester.toml +77 -0
- flock/themes/ciapre.toml +77 -0
- flock/themes/clrs.toml +77 -0
- flock/themes/cobalt-neon.toml +77 -0
- flock/themes/cobalt2.toml +77 -0
- flock/themes/coffee-theme.toml +77 -0
- flock/themes/crayonponyfish.toml +77 -0
- flock/themes/cutiepro.toml +77 -0
- flock/themes/cyberdyne.toml +77 -0
- flock/themes/cyberpunk.toml +77 -0
- flock/themes/cyberpunkscarletprotocol.toml +77 -0
- flock/themes/dark+.toml +77 -0
- flock/themes/dark-pastel.toml +77 -0
- flock/themes/darkermatrix.toml +77 -0
- flock/themes/darkmatrix.toml +77 -0
- flock/themes/darkside.toml +77 -0
- flock/themes/dayfox.toml +77 -0
- flock/themes/deep.toml +77 -0
- flock/themes/desert.toml +77 -0
- flock/themes/dimidium.toml +77 -0
- flock/themes/dimmedmonokai.toml +77 -0
- flock/themes/django.toml +77 -0
- flock/themes/djangorebornagain.toml +77 -0
- flock/themes/djangosmooth.toml +77 -0
- flock/themes/doom-peacock.toml +77 -0
- flock/themes/doomone.toml +77 -0
- flock/themes/dotgov.toml +77 -0
- flock/themes/dracula+.toml +77 -0
- flock/themes/dracula.toml +77 -0
- flock/themes/duckbones.toml +77 -0
- flock/themes/duotone-dark.toml +77 -0
- flock/themes/earthsong.toml +77 -0
- flock/themes/elemental.toml +77 -0
- flock/themes/elementary.toml +77 -0
- flock/themes/encom.toml +77 -0
- flock/themes/espresso-libre.toml +77 -0
- flock/themes/espresso.toml +77 -0
- flock/themes/everblush.toml +77 -0
- flock/themes/fahrenheit.toml +77 -0
- flock/themes/fairyfloss.toml +77 -0
- flock/themes/farmhouse-dark.toml +77 -0
- flock/themes/farmhouse-light.toml +77 -0
- flock/themes/fideloper.toml +77 -0
- flock/themes/firefly-traditional.toml +77 -0
- flock/themes/firefoxdev.toml +77 -0
- flock/themes/firewatch.toml +77 -0
- flock/themes/fishtank.toml +77 -0
- flock/themes/flat.toml +77 -0
- flock/themes/flatland.toml +77 -0
- flock/themes/flexoki-dark.toml +77 -0
- flock/themes/flexoki-light.toml +77 -0
- flock/themes/floraverse.toml +77 -0
- flock/themes/forestblue.toml +77 -0
- flock/themes/framer.toml +77 -0
- flock/themes/frontenddelight.toml +77 -0
- flock/themes/funforrest.toml +77 -0
- flock/themes/galaxy.toml +77 -0
- flock/themes/galizur.toml +77 -0
- flock/themes/github-dark.toml +77 -0
- flock/themes/github.toml +77 -0
- flock/themes/glacier.toml +77 -0
- flock/themes/grape.toml +77 -0
- flock/themes/grass.toml +77 -0
- flock/themes/grey-green.toml +77 -0
- flock/themes/gruber-darker.toml +77 -0
- flock/themes/gruvboxdark.toml +77 -0
- flock/themes/gruvboxdarkhard.toml +77 -0
- flock/themes/gruvboxlight.toml +77 -0
- flock/themes/guezwhoz.toml +77 -0
- flock/themes/hacktober.toml +77 -0
- flock/themes/hardcore.toml +77 -0
- flock/themes/harper.toml +77 -0
- flock/themes/hax0r-blue.toml +77 -0
- flock/themes/hax0r-gr33n.toml +77 -0
- flock/themes/hax0r-r3d.toml +77 -0
- flock/themes/highway.toml +77 -0
- flock/themes/hipster-green.toml +77 -0
- flock/themes/hivacruz.toml +77 -0
- flock/themes/homebrew.toml +77 -0
- flock/themes/hopscotch.256.toml +77 -0
- flock/themes/hopscotch.toml +77 -0
- flock/themes/hurtado.toml +77 -0
- flock/themes/hybrid.toml +77 -0
- flock/themes/ic-green-ppl.toml +77 -0
- flock/themes/ic-orange-ppl.toml +77 -0
- flock/themes/iceberg-dark.toml +77 -0
- flock/themes/iceberg-light.toml +77 -0
- flock/themes/idea.toml +77 -0
- flock/themes/idletoes.toml +77 -0
- flock/themes/ir-black.toml +77 -0
- flock/themes/iterm2-dark-background.toml +77 -0
- flock/themes/iterm2-default.toml +77 -0
- flock/themes/iterm2-light-background.toml +77 -0
- flock/themes/iterm2-pastel-dark-background.toml +77 -0
- flock/themes/iterm2-smoooooth.toml +77 -0
- flock/themes/iterm2-solarized-dark.toml +77 -0
- flock/themes/iterm2-solarized-light.toml +77 -0
- flock/themes/iterm2-tango-dark.toml +77 -0
- flock/themes/iterm2-tango-light.toml +77 -0
- flock/themes/jackie-brown.toml +77 -0
- flock/themes/japanesque.toml +77 -0
- flock/themes/jellybeans.toml +77 -0
- flock/themes/jetbrains-darcula.toml +77 -0
- flock/themes/jubi.toml +77 -0
- flock/themes/kanagawabones.toml +77 -0
- flock/themes/kibble.toml +77 -0
- flock/themes/kolorit.toml +77 -0
- flock/themes/konsolas.toml +77 -0
- flock/themes/kurokula.toml +77 -0
- flock/themes/lab-fox.toml +77 -0
- flock/themes/laser.toml +77 -0
- flock/themes/later-this-evening.toml +77 -0
- flock/themes/lavandula.toml +77 -0
- flock/themes/liquidcarbon.toml +77 -0
- flock/themes/liquidcarbontransparent.toml +77 -0
- flock/themes/liquidcarbontransparentinverse.toml +77 -0
- flock/themes/lovelace.toml +77 -0
- flock/themes/man-page.toml +77 -0
- flock/themes/mariana.toml +77 -0
- flock/themes/material.toml +77 -0
- flock/themes/materialdark.toml +77 -0
- flock/themes/materialdarker.toml +77 -0
- flock/themes/materialdesigncolors.toml +77 -0
- flock/themes/materialocean.toml +77 -0
- flock/themes/mathias.toml +77 -0
- flock/themes/matrix.toml +77 -0
- flock/themes/medallion.toml +77 -0
- flock/themes/mellifluous.toml +77 -0
- flock/themes/midnight-in-mojave.toml +77 -0
- flock/themes/mirage.toml +77 -0
- flock/themes/misterioso.toml +77 -0
- flock/themes/molokai.toml +77 -0
- flock/themes/monalisa.toml +77 -0
- flock/themes/monokai-remastered.toml +77 -0
- flock/themes/monokai-soda.toml +77 -0
- flock/themes/monokai-vivid.toml +77 -0
- flock/themes/n0tch2k.toml +77 -0
- flock/themes/neobones-dark.toml +77 -0
- flock/themes/neobones-light.toml +77 -0
- flock/themes/neon.toml +77 -0
- flock/themes/neopolitan.toml +77 -0
- flock/themes/neutron.toml +77 -0
- flock/themes/night-owlish-light.toml +77 -0
- flock/themes/nightfox.toml +77 -0
- flock/themes/nightlion-v1.toml +77 -0
- flock/themes/nightlion-v2.toml +77 -0
- flock/themes/niji.toml +77 -0
- flock/themes/nocturnal-winter.toml +77 -0
- flock/themes/nord-light.toml +77 -0
- flock/themes/nord.toml +77 -0
- flock/themes/novel.toml +77 -0
- flock/themes/nvimdark.toml +77 -0
- flock/themes/nvimlight.toml +77 -0
- flock/themes/obsidian.toml +77 -0
- flock/themes/ocean.toml +77 -0
- flock/themes/oceanic-next.toml +77 -0
- flock/themes/oceanicmaterial.toml +77 -0
- flock/themes/ollie.toml +77 -0
- flock/themes/onehalfdark.toml +77 -0
- flock/themes/onehalflight.toml +77 -0
- flock/themes/operator-mono-dark.toml +77 -0
- flock/themes/overnight-slumber.toml +77 -0
- flock/themes/oxocarbon.toml +77 -0
- flock/themes/palenighthc.toml +77 -0
- flock/themes/pandora.toml +77 -0
- flock/themes/paraiso-dark.toml +77 -0
- flock/themes/paulmillr.toml +77 -0
- flock/themes/pencildark.toml +77 -0
- flock/themes/pencillight.toml +77 -0
- flock/themes/peppermint.toml +77 -0
- flock/themes/piatto-light.toml +77 -0
- flock/themes/pnevma.toml +77 -0
- flock/themes/popping-and-locking.toml +77 -0
- flock/themes/primary.toml +77 -0
- flock/themes/pro-light.toml +77 -0
- flock/themes/pro.toml +77 -0
- flock/themes/purple-rain.toml +77 -0
- flock/themes/purplepeter.toml +77 -0
- flock/themes/rapture.toml +77 -0
- flock/themes/raycast-dark.toml +77 -0
- flock/themes/raycast-light.toml +77 -0
- flock/themes/rebecca.toml +77 -0
- flock/themes/red-alert.toml +77 -0
- flock/themes/red-planet.toml +77 -0
- flock/themes/red-sands.toml +77 -0
- flock/themes/relaxed.toml +77 -0
- flock/themes/retro.toml +77 -0
- flock/themes/rippedcasts.toml +77 -0
- flock/themes/rose-pine-dawn.toml +77 -0
- flock/themes/rose-pine-moon.toml +77 -0
- flock/themes/rose-pine.toml +77 -0
- flock/themes/rouge-2.toml +77 -0
- flock/themes/royal.toml +77 -0
- flock/themes/ryuuko.toml +77 -0
- flock/themes/sakura.toml +77 -0
- flock/themes/scarlet-protocol.toml +77 -0
- flock/themes/seafoam-pastel.toml +77 -0
- flock/themes/seashells.toml +77 -0
- flock/themes/seoulbones-dark.toml +77 -0
- flock/themes/seoulbones-light.toml +77 -0
- flock/themes/seti.toml +77 -0
- flock/themes/shades-of-purple.toml +77 -0
- flock/themes/shaman.toml +77 -0
- flock/themes/slate.toml +77 -0
- flock/themes/sleepyhollow.toml +77 -0
- flock/themes/smyck.toml +77 -0
- flock/themes/snazzy.toml +77 -0
- flock/themes/softserver.toml +77 -0
- flock/themes/solarized-darcula.toml +77 -0
- flock/themes/solarized-dark---patched.toml +77 -0
- flock/themes/solarized-dark-higher-contrast.toml +77 -0
- flock/themes/spacedust.toml +77 -0
- flock/themes/spacegray-eighties-dull.toml +77 -0
- flock/themes/spacegray-eighties.toml +77 -0
- flock/themes/spacegray.toml +77 -0
- flock/themes/spiderman.toml +77 -0
- flock/themes/spring.toml +77 -0
- flock/themes/square.toml +77 -0
- flock/themes/sublette.toml +77 -0
- flock/themes/subliminal.toml +77 -0
- flock/themes/sugarplum.toml +77 -0
- flock/themes/sundried.toml +77 -0
- flock/themes/symfonic.toml +77 -0
- flock/themes/synthwave-everything.toml +77 -0
- flock/themes/synthwave.toml +77 -0
- flock/themes/synthwavealpha.toml +77 -0
- flock/themes/tango-adapted.toml +77 -0
- flock/themes/tango-half-adapted.toml +77 -0
- flock/themes/teerb.toml +77 -0
- flock/themes/terafox.toml +77 -0
- flock/themes/terminal-basic.toml +77 -0
- flock/themes/thayer-bright.toml +77 -0
- flock/themes/the-hulk.toml +77 -0
- flock/themes/tinacious-design-(dark).toml +77 -0
- flock/themes/tinacious-design-(light).toml +77 -0
- flock/themes/tokyonight-day.toml +77 -0
- flock/themes/tokyonight-storm.toml +77 -0
- flock/themes/tokyonight.toml +77 -0
- flock/themes/tomorrow-night-blue.toml +77 -0
- flock/themes/tomorrow-night-bright.toml +77 -0
- flock/themes/tomorrow-night-burns.toml +77 -0
- flock/themes/tomorrow-night-eighties.toml +77 -0
- flock/themes/tomorrow-night.toml +77 -0
- flock/themes/tomorrow.toml +77 -0
- flock/themes/toychest.toml +77 -0
- flock/themes/treehouse.toml +77 -0
- flock/themes/twilight.toml +77 -0
- flock/themes/ubuntu.toml +77 -0
- flock/themes/ultradark.toml +77 -0
- flock/themes/ultraviolent.toml +77 -0
- flock/themes/underthesea.toml +77 -0
- flock/themes/unikitty.toml +77 -0
- flock/themes/urple.toml +77 -0
- flock/themes/vaughn.toml +77 -0
- flock/themes/vesper.toml +77 -0
- flock/themes/vibrantink.toml +77 -0
- flock/themes/vimbones.toml +77 -0
- flock/themes/violet-dark.toml +77 -0
- flock/themes/violet-light.toml +77 -0
- flock/themes/warmneon.toml +77 -0
- flock/themes/wez.toml +77 -0
- flock/themes/whimsy.toml +77 -0
- flock/themes/wildcherry.toml +77 -0
- flock/themes/wilmersdorf.toml +77 -0
- flock/themes/wombat.toml +77 -0
- flock/themes/wryan.toml +77 -0
- flock/themes/xcodedark.toml +77 -0
- flock/themes/xcodedarkhc.toml +77 -0
- flock/themes/xcodelight.toml +77 -0
- flock/themes/xcodelighthc.toml +77 -0
- flock/themes/xcodewwdc.toml +77 -0
- flock/themes/zenbones-dark.toml +77 -0
- flock/themes/zenbones-light.toml +77 -0
- flock/themes/zenbones.toml +77 -0
- flock/themes/zenburn.toml +77 -0
- flock/themes/zenburned.toml +77 -0
- flock/themes/zenwritten-dark.toml +77 -0
- flock/themes/zenwritten-light.toml +77 -0
- flock/workflow/activities.py +175 -115
- flock/workflow/agent_activities.py +24 -26
- flock/workflow/temporal_setup.py +38 -37
- flock/workflow/workflow.py +58 -53
- flock_core-0.2.2.dist-info/METADATA +320 -0
- flock_core-0.2.2.dist-info/RECORD +372 -0
- {flock_core-0.1.2.dist-info → flock_core-0.2.2.dist-info}/licenses/LICENSE +21 -21
- flock/agents/__init__.py +0 -3
- flock/agents/batch_agent.py +0 -175
- flock/agents/declarative_agent.py +0 -166
- flock/agents/loop_agent.py +0 -178
- flock/agents/trigger_agent.py +0 -191
- flock/agents/user_agent.py +0 -230
- flock/app/components/__init__.py +0 -14
- flock/app/components/charts/agent_workflow.py +0 -14
- flock/app/components/charts/core_architecture.py +0 -14
- flock/app/components/charts/tool_system.py +0 -14
- flock/app/components/history_grid.py +0 -168
- flock/app/components/history_grid_alt.py +0 -189
- flock/app/components/sidebar.py +0 -19
- flock/app/components/theme.py +0 -9
- flock/app/components/util.py +0 -18
- flock/app/hive_app.py +0 -118
- flock/app/html/d3.html +0 -179
- flock/app/modules/__init__.py +0 -12
- flock/app/modules/about.py +0 -17
- flock/app/modules/agent_detail.py +0 -70
- flock/app/modules/agent_list.py +0 -59
- flock/app/modules/playground.py +0 -322
- flock/app/modules/settings.py +0 -96
- flock/core/agent.py +0 -150
- flock/core/agent_registry.py +0 -162
- flock/core/context.py +0 -279
- flock/core/handoff/handoff_base.py +0 -12
- flock/core/logging/error_handler.py +0 -84
- flock/core/logging/formatters.py +0 -122
- flock/core/logging/handlers.py +0 -117
- flock/core/logging/logger.py +0 -107
- flock/core/serializable.py +0 -206
- flock_core-0.1.2.dist-info/METADATA +0 -476
- flock_core-0.1.2.dist-info/RECORD +0 -48
- flock_core-0.1.2.dist-info/entry_points.txt +0 -2
- /flock/{core/config/declarative_agent_config.py → workflow/__init__.py} +0 -0
- {flock_core-0.1.2.dist-info → flock_core-0.2.2.dist-info}/WHEEL +0 -0
|
@@ -1,166 +0,0 @@
|
|
|
1
|
-
from collections.abc import Callable
|
|
2
|
-
from typing import Any
|
|
3
|
-
|
|
4
|
-
import dspy # your dspy package for LM, Predict, ReAct, etc.
|
|
5
|
-
from pydantic import Field
|
|
6
|
-
|
|
7
|
-
from flock.core.agent import Agent
|
|
8
|
-
from flock.core.context import FlockContext
|
|
9
|
-
from flock.core.logging import flock_logger, performance_handler
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
class DeclarativeAgent(Agent):
|
|
13
|
-
"""An agent that evaluates declarative inputs.
|
|
14
|
-
|
|
15
|
-
Attributes:
|
|
16
|
-
input: A comma‐separated list of input keys.
|
|
17
|
-
If a key is not found in the incoming FlockContext and only one input is expected,
|
|
18
|
-
then the value of "init_input" is used.
|
|
19
|
-
output: A comma‐separated list of output keys (any type annotations after ":" are ignored).
|
|
20
|
-
tools: An optional list of callables (tools) that the agent is allowed to use.
|
|
21
|
-
use_cache: Whether to cache agent results.
|
|
22
|
-
"""
|
|
23
|
-
|
|
24
|
-
input: str = Field(description="Comma-separated input keys (e.g., 'blog_idea' or 'url, context')")
|
|
25
|
-
output: str = Field(description="Comma-separated output keys (e.g., 'title, headers')")
|
|
26
|
-
tools: list[Callable[..., Any]] | None = Field(default=None, description="Tools the agent is allowed to use")
|
|
27
|
-
use_cache: bool = Field(default=False, description="Whether to use the cache for this agent")
|
|
28
|
-
|
|
29
|
-
def _parse_keys(self, keys_str: str) -> list[str]:
|
|
30
|
-
"""Split a comma‐separated string and strip any type annotations.
|
|
31
|
-
For example, "a, b: list[str]" becomes ["a", "b"].
|
|
32
|
-
"""
|
|
33
|
-
keys = []
|
|
34
|
-
for part in keys_str.split(","):
|
|
35
|
-
part = part.strip()
|
|
36
|
-
if not part:
|
|
37
|
-
continue
|
|
38
|
-
# Remove any type annotation (everything after a colon)
|
|
39
|
-
if ":" in part:
|
|
40
|
-
key = part.split(":", 1)[0].strip()
|
|
41
|
-
else:
|
|
42
|
-
key = part
|
|
43
|
-
keys.append(key)
|
|
44
|
-
return keys
|
|
45
|
-
|
|
46
|
-
def _build_input(self, context: FlockContext) -> dict:
|
|
47
|
-
"""Build the dictionary of inputs for the agent based on its input specification.
|
|
48
|
-
|
|
49
|
-
For each key in the agent's input string:
|
|
50
|
-
- If the key is "context" (case-insensitive), pass the entire FlockContext.
|
|
51
|
-
- Otherwise, use context.get_variable() to fetch the value.
|
|
52
|
-
- If the key is not found and only one key is expected, default to context["init_input"].
|
|
53
|
-
"""
|
|
54
|
-
input_keys = self._parse_keys(self.input)
|
|
55
|
-
inputs = {}
|
|
56
|
-
for key in input_keys:
|
|
57
|
-
if key.lower() == "context":
|
|
58
|
-
inputs[key] = context
|
|
59
|
-
else:
|
|
60
|
-
value = context.get_variable(key)
|
|
61
|
-
if value is None and len(input_keys) == 1:
|
|
62
|
-
value = context.get_variable("init_input")
|
|
63
|
-
inputs[key] = value
|
|
64
|
-
return inputs
|
|
65
|
-
|
|
66
|
-
def _configure_task(self):
|
|
67
|
-
"""Configure the dspy language model and choose a task constructor.
|
|
68
|
-
If tools are provided, ReAct is used; otherwise, Predict.
|
|
69
|
-
"""
|
|
70
|
-
with performance_handler.track_time("model_configuration"):
|
|
71
|
-
flock_logger.debug(f"Configuring {self.model} for {'ReAct' if self.tools else 'Predict'} task")
|
|
72
|
-
lm = dspy.LM(self.model)
|
|
73
|
-
dspy.configure(lm=lm)
|
|
74
|
-
return dspy.ReAct if self.tools else dspy.Predict
|
|
75
|
-
|
|
76
|
-
async def _evaluate(self, context: FlockContext, input_overrides: dict | None = None) -> dict:
|
|
77
|
-
"""Evaluate the agent by:
|
|
78
|
-
1. Building an input dictionary from the FlockContext (merging any overrides),
|
|
79
|
-
2. Building a prompt like "input1, input2 -> output1, output2",
|
|
80
|
-
3. Instantiating and executing the dspy task (Predict or ReAct),
|
|
81
|
-
4. Returning the resulting dictionary.
|
|
82
|
-
"""
|
|
83
|
-
try:
|
|
84
|
-
# Build inputs
|
|
85
|
-
with performance_handler.track_time("input_preparation"):
|
|
86
|
-
inputs = self._build_input(context)
|
|
87
|
-
if input_overrides:
|
|
88
|
-
inputs.update(input_overrides)
|
|
89
|
-
input_keys = self._parse_keys(self.input)
|
|
90
|
-
output_keys = self._parse_keys(self.output)
|
|
91
|
-
prompt = f"{', '.join(input_keys)} -> {', '.join(output_keys)}"
|
|
92
|
-
flock_logger.debug("Prepared inputs", inputs=inputs, prompt=prompt)
|
|
93
|
-
|
|
94
|
-
# Configure and execute task
|
|
95
|
-
with performance_handler.track_time("task_execution"):
|
|
96
|
-
task_constructor = self._configure_task()
|
|
97
|
-
if self.tools:
|
|
98
|
-
flock_logger.info("Creating ReAct task with tools", num_tools=len(self.tools))
|
|
99
|
-
agent_task = task_constructor(prompt, tools=self.tools)
|
|
100
|
-
else:
|
|
101
|
-
flock_logger.info("Creating Predict task")
|
|
102
|
-
agent_task = task_constructor(prompt)
|
|
103
|
-
|
|
104
|
-
flock_logger.info("Executing task...")
|
|
105
|
-
result = agent_task(**inputs).toDict()
|
|
106
|
-
|
|
107
|
-
# Process result
|
|
108
|
-
for key in input_keys:
|
|
109
|
-
result.setdefault(key, inputs.get(key))
|
|
110
|
-
flock_logger.success("Task completed successfully", output_keys=list(result.keys()))
|
|
111
|
-
return result
|
|
112
|
-
|
|
113
|
-
except Exception as e:
|
|
114
|
-
flock_logger.error(
|
|
115
|
-
"Task execution failed",
|
|
116
|
-
error=str(e),
|
|
117
|
-
agent=self.name,
|
|
118
|
-
inputs=inputs,
|
|
119
|
-
prompt=prompt,
|
|
120
|
-
)
|
|
121
|
-
raise
|
|
122
|
-
|
|
123
|
-
async def run(self, context: FlockContext) -> dict:
|
|
124
|
-
"""Run the agent on the provided FlockContext (locally)."""
|
|
125
|
-
flock_logger.info(f"Running agent locally: {self.name}")
|
|
126
|
-
return await self._evaluate(context)
|
|
127
|
-
|
|
128
|
-
async def run_temporal(self, context: FlockContext) -> dict:
|
|
129
|
-
"""Run the agent via Temporal by serializing its parameters and the FlockContext and
|
|
130
|
-
calling a dedicated Temporal activity.
|
|
131
|
-
"""
|
|
132
|
-
from temporalio.client import Client
|
|
133
|
-
|
|
134
|
-
from flock.workflow.agent_activities import run_declarative_agent_activity
|
|
135
|
-
from flock.workflow.temporal_setup import run_activity
|
|
136
|
-
|
|
137
|
-
try:
|
|
138
|
-
with performance_handler.track_time("temporal_setup"):
|
|
139
|
-
# Connect to Temporal (adjust the host/namespace as needed)
|
|
140
|
-
flock_logger.info("Connecting to Temporal...")
|
|
141
|
-
client = await Client.connect("localhost:7233", namespace="default")
|
|
142
|
-
|
|
143
|
-
# Serialize the FlockContext and agent
|
|
144
|
-
flock_logger.debug("Serializing context and agent data")
|
|
145
|
-
context_data = {
|
|
146
|
-
"state": context.state,
|
|
147
|
-
"history": [record.__dict__ for record in context.history],
|
|
148
|
-
"agent_definitions": [definition.__dict__ for definition in context.agent_definitions],
|
|
149
|
-
}
|
|
150
|
-
agent_data = self.dict()
|
|
151
|
-
|
|
152
|
-
# Run the activity
|
|
153
|
-
with performance_handler.track_time("temporal_activity"):
|
|
154
|
-
flock_logger.info(f"Starting Temporal activity: {self.name}")
|
|
155
|
-
result = await run_activity(
|
|
156
|
-
client,
|
|
157
|
-
self.name,
|
|
158
|
-
run_declarative_agent_activity,
|
|
159
|
-
{"agent_data": agent_data, "context_data": context_data},
|
|
160
|
-
)
|
|
161
|
-
flock_logger.success("Temporal activity completed successfully")
|
|
162
|
-
return result
|
|
163
|
-
|
|
164
|
-
except Exception as e:
|
|
165
|
-
flock_logger.error(f"Temporal execution failed: {e}", agent=self.name)
|
|
166
|
-
raise
|
flock/agents/loop_agent.py
DELETED
|
@@ -1,178 +0,0 @@
|
|
|
1
|
-
from collections.abc import Callable
|
|
2
|
-
from typing import Any
|
|
3
|
-
|
|
4
|
-
from pydantic import Field
|
|
5
|
-
|
|
6
|
-
from flock.core.agent import Agent
|
|
7
|
-
from flock.core.context import FlockContext
|
|
8
|
-
from flock.core.logging import flock_logger, live_update_handler, performance_handler
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
class LoopAgent(Agent):
|
|
12
|
-
"""An agent that executes its logic in a loop until a termination condition is met.
|
|
13
|
-
|
|
14
|
-
Attributes:
|
|
15
|
-
input: Input domain for the agent
|
|
16
|
-
output: Output types for the agent
|
|
17
|
-
tools: Tools the agent is allowed to use
|
|
18
|
-
max_iterations: Maximum number of iterations before forced termination
|
|
19
|
-
termination_condition: Optional callable that determines when to stop the loop
|
|
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
|
-
max_iterations: int = Field(default=10, description="Maximum number of iterations")
|
|
26
|
-
termination_condition: Callable[[dict[str, Any]], bool] | None = Field(
|
|
27
|
-
default=None, description="Optional function to determine loop termination"
|
|
28
|
-
)
|
|
29
|
-
|
|
30
|
-
async def _process_iteration(self, context: FlockContext, iteration: int) -> dict[str, Any]:
|
|
31
|
-
"""Process a single iteration of the loop."""
|
|
32
|
-
try:
|
|
33
|
-
with performance_handler.track_time(f"iteration_{iteration}"):
|
|
34
|
-
flock_logger.debug(f"Processing iteration {iteration}", agent=self.name)
|
|
35
|
-
# Here you would implement the actual iteration logic
|
|
36
|
-
# For now, we'll just return a simple result
|
|
37
|
-
return {"iteration": iteration, "status": "completed"}
|
|
38
|
-
except Exception as e:
|
|
39
|
-
flock_logger.error(
|
|
40
|
-
f"Error in iteration {iteration}",
|
|
41
|
-
error=str(e),
|
|
42
|
-
agent=self.name,
|
|
43
|
-
)
|
|
44
|
-
raise
|
|
45
|
-
|
|
46
|
-
def _should_continue(self, result: dict[str, Any], iteration: int) -> bool:
|
|
47
|
-
"""Determine if the loop should continue."""
|
|
48
|
-
if iteration >= self.max_iterations:
|
|
49
|
-
flock_logger.warning(
|
|
50
|
-
"Maximum iterations reached",
|
|
51
|
-
max_iterations=self.max_iterations,
|
|
52
|
-
agent=self.name,
|
|
53
|
-
)
|
|
54
|
-
return False
|
|
55
|
-
|
|
56
|
-
if self.termination_condition:
|
|
57
|
-
should_terminate = self.termination_condition(result)
|
|
58
|
-
if should_terminate:
|
|
59
|
-
flock_logger.info(
|
|
60
|
-
"Termination condition met",
|
|
61
|
-
iteration=iteration,
|
|
62
|
-
agent=self.name,
|
|
63
|
-
)
|
|
64
|
-
return not should_terminate
|
|
65
|
-
|
|
66
|
-
return True
|
|
67
|
-
|
|
68
|
-
async def run(self, context: FlockContext) -> dict[str, Any]:
|
|
69
|
-
"""Run the agent in a loop until the termination condition is met or max iterations reached."""
|
|
70
|
-
try:
|
|
71
|
-
flock_logger.info(f"Starting loop agent: {self.name}")
|
|
72
|
-
results = []
|
|
73
|
-
iteration = 0
|
|
74
|
-
|
|
75
|
-
with live_update_handler.progress_tracker("Loop Progress") as update_progress:
|
|
76
|
-
while True:
|
|
77
|
-
# Update progress based on iteration count
|
|
78
|
-
progress = min((iteration + 1) * 100 / self.max_iterations, 100)
|
|
79
|
-
update_progress(progress)
|
|
80
|
-
|
|
81
|
-
# Process iteration with status tracking
|
|
82
|
-
with live_update_handler.update_activity_status(
|
|
83
|
-
f"{self.name}_iteration_{iteration}",
|
|
84
|
-
f"Iteration {iteration + 1}",
|
|
85
|
-
"Running",
|
|
86
|
-
{"max_iterations": self.max_iterations},
|
|
87
|
-
):
|
|
88
|
-
result = await self._process_iteration(context, iteration)
|
|
89
|
-
results.append(result)
|
|
90
|
-
|
|
91
|
-
# Check termination conditions
|
|
92
|
-
if not self._should_continue(result, iteration):
|
|
93
|
-
break
|
|
94
|
-
|
|
95
|
-
iteration += 1
|
|
96
|
-
|
|
97
|
-
flock_logger.success(
|
|
98
|
-
f"Loop completed successfully",
|
|
99
|
-
total_iterations=iteration + 1,
|
|
100
|
-
agent=self.name,
|
|
101
|
-
)
|
|
102
|
-
return {
|
|
103
|
-
"iterations": iteration + 1,
|
|
104
|
-
"results": results,
|
|
105
|
-
"final_result": results[-1] if results else None,
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
except Exception as e:
|
|
109
|
-
flock_logger.error(
|
|
110
|
-
"Loop execution failed",
|
|
111
|
-
error=str(e),
|
|
112
|
-
agent=self.name,
|
|
113
|
-
iteration=iteration,
|
|
114
|
-
)
|
|
115
|
-
raise
|
|
116
|
-
|
|
117
|
-
async def run_temporal(self, context: FlockContext) -> dict[str, Any]:
|
|
118
|
-
"""Run the loop agent via Temporal."""
|
|
119
|
-
try:
|
|
120
|
-
from temporalio.client import Client
|
|
121
|
-
|
|
122
|
-
from flock.workflow.agent_activities import run_agent_activity
|
|
123
|
-
from flock.workflow.temporal_setup import run_activity
|
|
124
|
-
|
|
125
|
-
with performance_handler.track_time("temporal_setup"):
|
|
126
|
-
flock_logger.info(f"Starting temporal loop agent: {self.name}")
|
|
127
|
-
client = await Client.connect("localhost:7233", namespace="default")
|
|
128
|
-
|
|
129
|
-
results = []
|
|
130
|
-
iteration = 0
|
|
131
|
-
|
|
132
|
-
with live_update_handler.update_workflow_status(
|
|
133
|
-
self.name, "Running", {"phase": "loop_execution", "max_iterations": self.max_iterations}
|
|
134
|
-
):
|
|
135
|
-
while True:
|
|
136
|
-
# Process iteration as a temporal activity
|
|
137
|
-
with performance_handler.track_time(f"temporal_iteration_{iteration}"):
|
|
138
|
-
context_data = {
|
|
139
|
-
"state": context.state,
|
|
140
|
-
"history": [record.__dict__ for record in context.history],
|
|
141
|
-
"agent_definitions": [definition.__dict__ for definition in context.agent_definitions],
|
|
142
|
-
}
|
|
143
|
-
agent_data = self.dict()
|
|
144
|
-
|
|
145
|
-
flock_logger.info(f"Starting temporal iteration {iteration + 1}")
|
|
146
|
-
result = await run_activity(
|
|
147
|
-
client,
|
|
148
|
-
f"{self.name}_iteration_{iteration}",
|
|
149
|
-
run_agent_activity,
|
|
150
|
-
{"agent_data": agent_data, "context_data": context_data},
|
|
151
|
-
)
|
|
152
|
-
results.append(result)
|
|
153
|
-
|
|
154
|
-
# Check termination conditions
|
|
155
|
-
if not self._should_continue(result, iteration):
|
|
156
|
-
break
|
|
157
|
-
|
|
158
|
-
iteration += 1
|
|
159
|
-
|
|
160
|
-
flock_logger.success(
|
|
161
|
-
"Temporal loop completed successfully",
|
|
162
|
-
total_iterations=iteration + 1,
|
|
163
|
-
agent=self.name,
|
|
164
|
-
)
|
|
165
|
-
return {
|
|
166
|
-
"iterations": iteration + 1,
|
|
167
|
-
"results": results,
|
|
168
|
-
"final_result": results[-1] if results else None,
|
|
169
|
-
}
|
|
170
|
-
|
|
171
|
-
except Exception as e:
|
|
172
|
-
flock_logger.error(
|
|
173
|
-
"Temporal loop execution failed",
|
|
174
|
-
error=str(e),
|
|
175
|
-
agent=self.name,
|
|
176
|
-
iteration=iteration,
|
|
177
|
-
)
|
|
178
|
-
raise
|
flock/agents/trigger_agent.py
DELETED
|
@@ -1,191 +0,0 @@
|
|
|
1
|
-
from collections.abc import Callable
|
|
2
|
-
from typing import Any
|
|
3
|
-
|
|
4
|
-
from pydantic import Field
|
|
5
|
-
|
|
6
|
-
from flock.core.agent import Agent
|
|
7
|
-
from flock.core.context import FlockContext
|
|
8
|
-
from flock.core.logging import flock_logger, live_update_handler, performance_handler
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
class TriggerAgent(Agent):
|
|
12
|
-
"""An agent that executes based on specific triggers/conditions.
|
|
13
|
-
|
|
14
|
-
Attributes:
|
|
15
|
-
input: Input domain for the agent
|
|
16
|
-
output: Output types for the agent
|
|
17
|
-
tools: Tools the agent is allowed to use
|
|
18
|
-
trigger_condition: Callable that evaluates whether the agent should execute
|
|
19
|
-
trigger_check_interval: How often to check the trigger condition (in seconds)
|
|
20
|
-
max_wait_time: Maximum time to wait for trigger (in seconds)
|
|
21
|
-
"""
|
|
22
|
-
|
|
23
|
-
input: str = Field(default="", description="Input domain for the agent")
|
|
24
|
-
output: str = Field(default="", description="Output types for the agent")
|
|
25
|
-
tools: list[Callable] | None = Field(default=None, description="Tools the agent is allowed to use")
|
|
26
|
-
trigger_condition: Callable[[dict[str, Any]], bool] = Field(
|
|
27
|
-
..., description="Function that evaluates trigger conditions"
|
|
28
|
-
)
|
|
29
|
-
trigger_check_interval: float = Field(default=1.0, description="Interval between trigger checks (seconds)")
|
|
30
|
-
max_wait_time: float = Field(default=60.0, description="Maximum time to wait for trigger (seconds)")
|
|
31
|
-
|
|
32
|
-
async def _evaluate_trigger(self, context: FlockContext) -> bool:
|
|
33
|
-
"""Evaluate the trigger condition."""
|
|
34
|
-
try:
|
|
35
|
-
with performance_handler.track_time("trigger_evaluation"):
|
|
36
|
-
flock_logger.debug("Evaluating trigger condition", agent=self.name)
|
|
37
|
-
result = self.trigger_condition(context.state)
|
|
38
|
-
flock_logger.debug(
|
|
39
|
-
"Trigger evaluation result",
|
|
40
|
-
triggered=result,
|
|
41
|
-
agent=self.name,
|
|
42
|
-
)
|
|
43
|
-
return result
|
|
44
|
-
except Exception as e:
|
|
45
|
-
flock_logger.error(
|
|
46
|
-
"Trigger evaluation failed",
|
|
47
|
-
error=str(e),
|
|
48
|
-
agent=self.name,
|
|
49
|
-
)
|
|
50
|
-
raise
|
|
51
|
-
|
|
52
|
-
async def _execute_action(self, context: FlockContext) -> dict[str, Any]:
|
|
53
|
-
"""Execute the agent's action once triggered."""
|
|
54
|
-
try:
|
|
55
|
-
with performance_handler.track_time("action_execution"):
|
|
56
|
-
flock_logger.info("Executing triggered action", agent=self.name)
|
|
57
|
-
# Here you would implement the actual action logic
|
|
58
|
-
# For now, we'll just return a simple result
|
|
59
|
-
result = {"status": "completed", "trigger_time": context.state.get("current_time")}
|
|
60
|
-
flock_logger.success("Action executed successfully", agent=self.name)
|
|
61
|
-
return result
|
|
62
|
-
except Exception as e:
|
|
63
|
-
flock_logger.error(
|
|
64
|
-
"Action execution failed",
|
|
65
|
-
error=str(e),
|
|
66
|
-
agent=self.name,
|
|
67
|
-
)
|
|
68
|
-
raise
|
|
69
|
-
|
|
70
|
-
async def run(self, context: FlockContext) -> dict[str, Any]:
|
|
71
|
-
"""Run the agent, waiting for and responding to triggers."""
|
|
72
|
-
import asyncio
|
|
73
|
-
import time
|
|
74
|
-
|
|
75
|
-
try:
|
|
76
|
-
flock_logger.info(f"Starting trigger agent: {self.name}")
|
|
77
|
-
start_time = time.time()
|
|
78
|
-
triggered = False
|
|
79
|
-
|
|
80
|
-
with live_update_handler.progress_tracker("Waiting for trigger") as update_progress:
|
|
81
|
-
while (time.time() - start_time) < self.max_wait_time:
|
|
82
|
-
# Update progress based on elapsed time
|
|
83
|
-
elapsed = time.time() - start_time
|
|
84
|
-
progress = min(elapsed * 100 / self.max_wait_time, 100)
|
|
85
|
-
update_progress(progress)
|
|
86
|
-
|
|
87
|
-
# Check trigger with status tracking
|
|
88
|
-
with live_update_handler.update_activity_status(
|
|
89
|
-
self.name,
|
|
90
|
-
"Checking Trigger",
|
|
91
|
-
"Running",
|
|
92
|
-
{
|
|
93
|
-
"elapsed_time": f"{elapsed:.1f}s",
|
|
94
|
-
"max_wait_time": f"{self.max_wait_time:.1f}s",
|
|
95
|
-
},
|
|
96
|
-
):
|
|
97
|
-
if await self._evaluate_trigger(context):
|
|
98
|
-
triggered = True
|
|
99
|
-
break
|
|
100
|
-
|
|
101
|
-
await asyncio.sleep(self.trigger_check_interval)
|
|
102
|
-
|
|
103
|
-
if not triggered:
|
|
104
|
-
flock_logger.warning(
|
|
105
|
-
"Trigger timeout reached",
|
|
106
|
-
max_wait_time=self.max_wait_time,
|
|
107
|
-
agent=self.name,
|
|
108
|
-
)
|
|
109
|
-
return {"error": "Trigger timeout", "max_wait_time": self.max_wait_time}
|
|
110
|
-
|
|
111
|
-
# Execute action when triggered
|
|
112
|
-
result = await self._execute_action(context)
|
|
113
|
-
return result
|
|
114
|
-
|
|
115
|
-
except Exception as e:
|
|
116
|
-
flock_logger.error(
|
|
117
|
-
"Trigger agent execution failed",
|
|
118
|
-
error=str(e),
|
|
119
|
-
agent=self.name,
|
|
120
|
-
)
|
|
121
|
-
raise
|
|
122
|
-
|
|
123
|
-
async def run_temporal(self, context: FlockContext) -> dict[str, Any]:
|
|
124
|
-
"""Run the trigger agent via Temporal."""
|
|
125
|
-
try:
|
|
126
|
-
from temporalio.client import Client
|
|
127
|
-
|
|
128
|
-
from flock.workflow.agent_activities import run_agent_activity
|
|
129
|
-
from flock.workflow.temporal_setup import run_activity
|
|
130
|
-
|
|
131
|
-
with performance_handler.track_time("temporal_setup"):
|
|
132
|
-
flock_logger.info(f"Starting temporal trigger agent: {self.name}")
|
|
133
|
-
client = await Client.connect("localhost:7233", namespace="default")
|
|
134
|
-
|
|
135
|
-
with live_update_handler.update_workflow_status(
|
|
136
|
-
self.name,
|
|
137
|
-
"Running",
|
|
138
|
-
{
|
|
139
|
-
"phase": "trigger_monitoring",
|
|
140
|
-
"check_interval": self.trigger_check_interval,
|
|
141
|
-
"max_wait_time": self.max_wait_time,
|
|
142
|
-
},
|
|
143
|
-
):
|
|
144
|
-
# First activity: Monitor trigger
|
|
145
|
-
context_data = {
|
|
146
|
-
"state": context.state,
|
|
147
|
-
"history": [record.__dict__ for record in context.history],
|
|
148
|
-
"agent_definitions": [definition.__dict__ for definition in context.agent_definitions],
|
|
149
|
-
}
|
|
150
|
-
agent_data = self.dict()
|
|
151
|
-
|
|
152
|
-
with performance_handler.track_time("temporal_trigger_monitoring"):
|
|
153
|
-
flock_logger.info("Starting trigger monitoring activity")
|
|
154
|
-
monitor_result = await run_activity(
|
|
155
|
-
client,
|
|
156
|
-
f"{self.name}_monitor",
|
|
157
|
-
run_agent_activity,
|
|
158
|
-
{"agent_data": agent_data, "context_data": context_data},
|
|
159
|
-
)
|
|
160
|
-
|
|
161
|
-
if monitor_result.get("error"):
|
|
162
|
-
flock_logger.warning(
|
|
163
|
-
"Trigger monitoring ended without activation",
|
|
164
|
-
reason=monitor_result["error"],
|
|
165
|
-
agent=self.name,
|
|
166
|
-
)
|
|
167
|
-
return monitor_result
|
|
168
|
-
|
|
169
|
-
# Second activity: Execute action
|
|
170
|
-
with performance_handler.track_time("temporal_action_execution"):
|
|
171
|
-
flock_logger.info("Starting action execution activity")
|
|
172
|
-
action_result = await run_activity(
|
|
173
|
-
client,
|
|
174
|
-
f"{self.name}_action",
|
|
175
|
-
run_agent_activity,
|
|
176
|
-
{"agent_data": agent_data, "context_data": context_data},
|
|
177
|
-
)
|
|
178
|
-
|
|
179
|
-
flock_logger.success(
|
|
180
|
-
"Temporal trigger agent completed successfully",
|
|
181
|
-
agent=self.name,
|
|
182
|
-
)
|
|
183
|
-
return action_result
|
|
184
|
-
|
|
185
|
-
except Exception as e:
|
|
186
|
-
flock_logger.error(
|
|
187
|
-
"Temporal trigger agent execution failed",
|
|
188
|
-
error=str(e),
|
|
189
|
-
agent=self.name,
|
|
190
|
-
)
|
|
191
|
-
raise
|