flock-core 0.1.2__py3-none-any.whl → 0.2.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/__init__.py +1 -4
- flock/agents/__init__.py +0 -3
- flock/agents/batch_agent.py +140 -175
- flock/agents/loop_agent.py +117 -178
- flock/agents/trigger_agent.py +113 -191
- flock/agents/user_agent.py +145 -230
- flock/core/__init__.py +1 -7
- flock/core/context/context.py +211 -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 +40 -0
- flock/core/flock.py +199 -208
- flock/core/flock_agent.py +492 -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 +123 -0
- flock/core/mixin/dspy_integration.py +171 -0
- flock/core/mixin/prompt_parser.py +125 -0
- flock/core/registry/agent_registry.py +103 -0
- flock/core/tools/basic_tools.py +273 -98
- flock/core/tools/dev_tools/github.py +161 -0
- flock/core/util/cli_helper.py +21 -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 +117 -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.1.dist-info/METADATA +287 -0
- flock_core-0.2.1.dist-info/RECORD +375 -0
- {flock_core-0.1.2.dist-info → flock_core-0.2.1.dist-info}/licenses/LICENSE +21 -21
- flock/agents/declarative_agent.py +0 -166
- 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.1.dist-info}/WHEEL +0 -0
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
from typing import Any
|
|
2
|
+
|
|
3
|
+
from devtools import pprint
|
|
4
|
+
from temporalio import workflow
|
|
5
|
+
|
|
6
|
+
from flock.core.logging.formatters.base_formatter import BaseFormatter
|
|
7
|
+
|
|
8
|
+
with workflow.unsafe.imports_passed_through():
|
|
9
|
+
from rich.console import Console, Group
|
|
10
|
+
from rich.panel import Panel
|
|
11
|
+
from rich.table import Table
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def create_rich_renderable(
|
|
15
|
+
value: Any,
|
|
16
|
+
level: int = 0,
|
|
17
|
+
max_length: int = -1,
|
|
18
|
+
) -> Any:
|
|
19
|
+
"""Recursively creates a Rich renderable for a given value.
|
|
20
|
+
|
|
21
|
+
- If the value is a dict, return a Table representing the dict.
|
|
22
|
+
- If the value is a list or tuple:
|
|
23
|
+
- If all items are dicts, return a Group of subtables.
|
|
24
|
+
- Otherwise, render each item recursively and either join them as text
|
|
25
|
+
(if all rendered items are strings) or return a Group.
|
|
26
|
+
- Otherwise, return a string (with extra newlines if it's a multi-line string).
|
|
27
|
+
"""
|
|
28
|
+
if isinstance(value, dict):
|
|
29
|
+
# Create a subtable for the dictionary.
|
|
30
|
+
# You can tweak the table styles or add a title that indicates the level.
|
|
31
|
+
table = Table(
|
|
32
|
+
show_header=True,
|
|
33
|
+
header_style="bold green",
|
|
34
|
+
title=f"Subtable (Level {level})" if level > 0 else None,
|
|
35
|
+
title_style="bold blue",
|
|
36
|
+
border_style="bright_blue",
|
|
37
|
+
show_lines=True,
|
|
38
|
+
)
|
|
39
|
+
table.add_column("Key", style="cyan")
|
|
40
|
+
table.add_column("Value", style="green")
|
|
41
|
+
for k, v in value.items():
|
|
42
|
+
table.add_row(
|
|
43
|
+
str(k),
|
|
44
|
+
create_rich_renderable(v, level + 1, max_length=max_length),
|
|
45
|
+
)
|
|
46
|
+
return table
|
|
47
|
+
|
|
48
|
+
elif isinstance(value, list | tuple):
|
|
49
|
+
# If all items are dicts, build a Group of subtables with an index.
|
|
50
|
+
if all(isinstance(item, dict) for item in value):
|
|
51
|
+
sub_tables = []
|
|
52
|
+
for i, item in enumerate(value):
|
|
53
|
+
sub_tables.append(f"[bold]Item {i + 1}[/bold]")
|
|
54
|
+
sub_tables.append(
|
|
55
|
+
create_rich_renderable(
|
|
56
|
+
item, level + 1, max_length=max_length
|
|
57
|
+
)
|
|
58
|
+
)
|
|
59
|
+
return Group(*sub_tables)
|
|
60
|
+
else:
|
|
61
|
+
# For a mixed list, render each item recursively.
|
|
62
|
+
rendered_items = [
|
|
63
|
+
create_rich_renderable(item, level + 1, max_length=max_length)
|
|
64
|
+
for item in value
|
|
65
|
+
]
|
|
66
|
+
# If all items ended up as strings, join them.
|
|
67
|
+
if all(isinstance(item, str) for item in rendered_items):
|
|
68
|
+
return "\n".join(rendered_items)
|
|
69
|
+
else:
|
|
70
|
+
return Group(*rendered_items)
|
|
71
|
+
|
|
72
|
+
else:
|
|
73
|
+
s = str(value).strip()
|
|
74
|
+
if max_length > 0 and len(s) > max_length:
|
|
75
|
+
omitted = len(s) - max_length
|
|
76
|
+
s = (
|
|
77
|
+
s[:max_length]
|
|
78
|
+
+ f"[bold bright_yellow]...(+{omitted}chars)[/bold bright_yellow]"
|
|
79
|
+
)
|
|
80
|
+
if isinstance(value, str) and "\n" in value:
|
|
81
|
+
return f"\n{s}\n"
|
|
82
|
+
return s
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
class RichTables(BaseFormatter):
|
|
86
|
+
"""Formats agent results in a beautiful Rich table with nested subtables."""
|
|
87
|
+
|
|
88
|
+
def __init__(self, max_length: int = -1):
|
|
89
|
+
self.max_length = max_length
|
|
90
|
+
|
|
91
|
+
def format_result(self, result: dict[str, Any], agent_name: str) -> Panel:
|
|
92
|
+
"""Format an agent's result as a Rich panel containing a table."""
|
|
93
|
+
# Create the main table.
|
|
94
|
+
table = Table(
|
|
95
|
+
show_lines=True,
|
|
96
|
+
show_header=True,
|
|
97
|
+
header_style="bold green",
|
|
98
|
+
title=f"Agent Results: {agent_name}",
|
|
99
|
+
title_style="bold blue",
|
|
100
|
+
border_style="bright_blue",
|
|
101
|
+
)
|
|
102
|
+
table.add_column("Output", style="cyan")
|
|
103
|
+
table.add_column("Value", style="green")
|
|
104
|
+
|
|
105
|
+
# For each key/value pair, use the recursive renderable.
|
|
106
|
+
for key, value in result.items():
|
|
107
|
+
rich_renderable = create_rich_renderable(
|
|
108
|
+
value, level=0, max_length=self.max_length
|
|
109
|
+
)
|
|
110
|
+
table.add_row(key, rich_renderable)
|
|
111
|
+
|
|
112
|
+
# Wrap the table in a panel.
|
|
113
|
+
return Panel(
|
|
114
|
+
table,
|
|
115
|
+
title="🐤🐧🐓🦆",
|
|
116
|
+
title_align="left",
|
|
117
|
+
border_style="blue",
|
|
118
|
+
padding=(1, 2),
|
|
119
|
+
)
|
|
120
|
+
|
|
121
|
+
def display_result(
|
|
122
|
+
self, result: dict[str, Any], agent_name: str, **kwargs
|
|
123
|
+
) -> None:
|
|
124
|
+
"""Print an agent's result using Rich formatting."""
|
|
125
|
+
console = Console()
|
|
126
|
+
panel = self.format_result(result=result, agent_name=agent_name)
|
|
127
|
+
# pprint(result) # Optional: Print the raw result with pprint.
|
|
128
|
+
console.print(panel)
|
|
129
|
+
|
|
130
|
+
def display_data(self, data: dict[str, Any], **kwargs) -> None:
|
|
131
|
+
"""Print an agent's result using Rich formatting."""
|
|
132
|
+
pprint(data)
|
|
@@ -0,0 +1,480 @@
|
|
|
1
|
+
#!/usr/bin/env python
|
|
2
|
+
"""A simple interactive theme builder.
|
|
3
|
+
|
|
4
|
+
Steps:
|
|
5
|
+
1. Load theme files from a folder (or pick N random ones).
|
|
6
|
+
2. Display each theme’s color palette (colors only).
|
|
7
|
+
3. Let the user choose a palette.
|
|
8
|
+
4. Generate a number of sample tables using that palette (with randomized non-color settings).
|
|
9
|
+
5. Let the user select one sample table and save its configuration to a TOML file.
|
|
10
|
+
"""
|
|
11
|
+
|
|
12
|
+
import pathlib
|
|
13
|
+
import random
|
|
14
|
+
import re
|
|
15
|
+
from typing import Any
|
|
16
|
+
|
|
17
|
+
import toml
|
|
18
|
+
from rich import box
|
|
19
|
+
from rich.console import Console, Group
|
|
20
|
+
from rich.panel import Panel
|
|
21
|
+
from rich.table import Table
|
|
22
|
+
from rich.text import Text
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
def resolve_style_string(style_str: str, theme: dict) -> str:
|
|
26
|
+
"""Replace tokens of the form "color.<section>.<key>" in style_str with
|
|
27
|
+
the value from theme["colors"][<section>][<key>].
|
|
28
|
+
"""
|
|
29
|
+
pattern = r"color\.(\w+)\.(\w+)"
|
|
30
|
+
|
|
31
|
+
def repl(match):
|
|
32
|
+
section = match.group(1)
|
|
33
|
+
key = match.group(2)
|
|
34
|
+
try:
|
|
35
|
+
return theme["colors"][section][key]
|
|
36
|
+
except KeyError:
|
|
37
|
+
return match.group(0)
|
|
38
|
+
|
|
39
|
+
return re.sub(pattern, repl, style_str)
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
def generate_default_rich_block(theme: dict | None = None) -> dict[str, Any]:
|
|
43
|
+
"""Generate a default [rich] block that includes:
|
|
44
|
+
- Color properties computed from the theme's [colors] blocks.
|
|
45
|
+
- Extra color tokens (so tokens like "color.bright.green" can be used).
|
|
46
|
+
- Non-color table layout properties, randomly chosen.
|
|
47
|
+
"""
|
|
48
|
+
|
|
49
|
+
def random_background():
|
|
50
|
+
return random.choice(
|
|
51
|
+
[
|
|
52
|
+
f"{normal_black}",
|
|
53
|
+
f"{normal_blue}",
|
|
54
|
+
f"{primary_background}",
|
|
55
|
+
f"{selection_background}",
|
|
56
|
+
f"{cursor_cursor}",
|
|
57
|
+
]
|
|
58
|
+
)
|
|
59
|
+
|
|
60
|
+
if theme is not None:
|
|
61
|
+
bright = theme["colors"].get("bright", {})
|
|
62
|
+
normal = theme["colors"].get("normal", {})
|
|
63
|
+
cursor = theme["colors"].get("cursor", {})
|
|
64
|
+
primary = theme["colors"].get("primary", {})
|
|
65
|
+
selection = theme["colors"].get("selection", {})
|
|
66
|
+
|
|
67
|
+
bright_black = bright.get("black", "#000000")
|
|
68
|
+
bright_blue = bright.get("blue", "#96cbfe")
|
|
69
|
+
bright_cyan = bright.get("cyan", "#85befd")
|
|
70
|
+
bright_green = bright.get("green", "#94fa36")
|
|
71
|
+
bright_magenta = bright.get("magenta", "#b9b6fc")
|
|
72
|
+
bright_red = bright.get("red", "#fd5ff1")
|
|
73
|
+
bright_white = bright.get("white", "#e0e0e0")
|
|
74
|
+
bright_yellow = bright.get("yellow", "#f5ffa8")
|
|
75
|
+
|
|
76
|
+
normal_black = normal.get("black", "#000000")
|
|
77
|
+
normal_blue = normal.get("blue", "#85befd")
|
|
78
|
+
normal_cyan = normal.get("cyan", "#85befd")
|
|
79
|
+
normal_green = normal.get("green", "#87c38a")
|
|
80
|
+
normal_magenta = normal.get("magenta", "#b9b6fc")
|
|
81
|
+
normal_red = normal.get("red", "#fd5ff1")
|
|
82
|
+
normal_white = normal.get("white", "#e0e0e0")
|
|
83
|
+
normal_yellow = normal.get("yellow", "#ffd7b1")
|
|
84
|
+
|
|
85
|
+
cursor_cursor = cursor.get("cursor", "#d0d0d0")
|
|
86
|
+
cursor_text = cursor.get("text", "#151515")
|
|
87
|
+
|
|
88
|
+
primary_background = primary.get("background", "#161719")
|
|
89
|
+
primary_foreground = primary.get("foreground", "#c5c8c6")
|
|
90
|
+
selection_background = selection.get("background", "#444444")
|
|
91
|
+
selection_text = selection.get("text", primary_foreground)
|
|
92
|
+
else:
|
|
93
|
+
# Fallback default values.
|
|
94
|
+
bright_black = "black"
|
|
95
|
+
bright_blue = "blue"
|
|
96
|
+
bright_cyan = "cyan"
|
|
97
|
+
bright_green = "green"
|
|
98
|
+
bright_magenta = "magenta"
|
|
99
|
+
bright_red = "red"
|
|
100
|
+
bright_white = "white"
|
|
101
|
+
bright_yellow = "yellow"
|
|
102
|
+
normal_black = "black"
|
|
103
|
+
normal_blue = "blue"
|
|
104
|
+
normal_cyan = "cyan"
|
|
105
|
+
normal_green = "green"
|
|
106
|
+
normal_magenta = "magenta"
|
|
107
|
+
normal_red = "red"
|
|
108
|
+
normal_white = "white"
|
|
109
|
+
normal_yellow = "yellow"
|
|
110
|
+
cursor_cursor = "gray"
|
|
111
|
+
cursor_text = "white"
|
|
112
|
+
primary_background = "black"
|
|
113
|
+
primary_foreground = "white"
|
|
114
|
+
selection_background = "gray"
|
|
115
|
+
selection_text = "white"
|
|
116
|
+
|
|
117
|
+
# Color properties.
|
|
118
|
+
default_color_props = {
|
|
119
|
+
"panel_style": f"on {random_background()}",
|
|
120
|
+
"table_header_style": f"bold {selection_text} on {selection_background}",
|
|
121
|
+
"table_title_style": f"bold {primary_foreground}",
|
|
122
|
+
"table_border_style": bright_blue,
|
|
123
|
+
"panel_border_style": bright_blue,
|
|
124
|
+
"column_output": f"bold {primary_foreground}",
|
|
125
|
+
"column_value": primary_foreground,
|
|
126
|
+
}
|
|
127
|
+
# Extra color tokens.
|
|
128
|
+
extra_color_props = {
|
|
129
|
+
"bright_black": bright_black,
|
|
130
|
+
"bright_blue": bright_blue,
|
|
131
|
+
"bright_cyan": bright_cyan,
|
|
132
|
+
"bright_green": bright_green,
|
|
133
|
+
"bright_magenta": bright_magenta,
|
|
134
|
+
"bright_red": bright_red,
|
|
135
|
+
"bright_white": bright_white,
|
|
136
|
+
"bright_yellow": bright_yellow,
|
|
137
|
+
"normal_black": normal_black,
|
|
138
|
+
"normal_blue": normal_blue,
|
|
139
|
+
"normal_cyan": normal_cyan,
|
|
140
|
+
"normal_green": normal_green,
|
|
141
|
+
"normal_magenta": normal_magenta,
|
|
142
|
+
"normal_red": normal_red,
|
|
143
|
+
"normal_white": normal_white,
|
|
144
|
+
"normal_yellow": normal_yellow,
|
|
145
|
+
"cursor_cursor": cursor_cursor,
|
|
146
|
+
"cursor_text": cursor_text,
|
|
147
|
+
}
|
|
148
|
+
# Non-color layout properties, randomly chosen.
|
|
149
|
+
default_non_color_props = {
|
|
150
|
+
"table_show_lines": random.choice([True, False]),
|
|
151
|
+
"table_box": random.choice(
|
|
152
|
+
["ROUNDED", "SIMPLE", "SQUARE", "MINIMAL", "HEAVY", "DOUBLE_EDGE"]
|
|
153
|
+
),
|
|
154
|
+
"panel_padding": random.choice([[1, 2], [1, 1], [2, 2], [0, 2]]),
|
|
155
|
+
"panel_title_align": random.choice(["left", "center", "right"]),
|
|
156
|
+
"table_row_styles": random.choice(
|
|
157
|
+
[["", "dim"], ["", "italic"], ["", "underline"]]
|
|
158
|
+
),
|
|
159
|
+
}
|
|
160
|
+
# Extra table layout properties (non-content).
|
|
161
|
+
default_extra_table_props = {
|
|
162
|
+
"table_safe_box": True,
|
|
163
|
+
"table_padding": [0, 1],
|
|
164
|
+
"table_collapse_padding": False,
|
|
165
|
+
"table_pad_edge": True,
|
|
166
|
+
"table_expand": False,
|
|
167
|
+
"table_show_footer": False,
|
|
168
|
+
"table_show_edge": True,
|
|
169
|
+
"table_leading": 0,
|
|
170
|
+
"table_style": "none",
|
|
171
|
+
"table_footer_style": "none",
|
|
172
|
+
"table_caption": "",
|
|
173
|
+
"table_caption_style": "none",
|
|
174
|
+
"table_title_justify": "center",
|
|
175
|
+
"table_caption_justify": "center",
|
|
176
|
+
"table_highlight": False,
|
|
177
|
+
}
|
|
178
|
+
defaults = {
|
|
179
|
+
**default_color_props,
|
|
180
|
+
**extra_color_props,
|
|
181
|
+
**default_non_color_props,
|
|
182
|
+
**default_extra_table_props,
|
|
183
|
+
}
|
|
184
|
+
return defaults
|
|
185
|
+
|
|
186
|
+
|
|
187
|
+
def load_theme_from_file(filepath: str) -> dict:
|
|
188
|
+
"""Load a theme from a TOML file.
|
|
189
|
+
|
|
190
|
+
If the file does not contain a [rich] block, one is generated and saved.
|
|
191
|
+
"""
|
|
192
|
+
with open(filepath) as f:
|
|
193
|
+
theme = toml.load(f)
|
|
194
|
+
if "rich" not in theme:
|
|
195
|
+
theme["rich"] = generate_default_rich_block(theme)
|
|
196
|
+
with open(filepath, "w") as f:
|
|
197
|
+
toml.dump(theme, f)
|
|
198
|
+
return theme
|
|
199
|
+
|
|
200
|
+
|
|
201
|
+
def get_default_styles(theme: dict | None) -> dict[str, Any]:
|
|
202
|
+
"""Build a style mapping from the theme by merging defaults with any overrides
|
|
203
|
+
in the [rich] block. Also resolves any color tokens.
|
|
204
|
+
"""
|
|
205
|
+
if theme is None:
|
|
206
|
+
final_styles = generate_default_rich_block(None)
|
|
207
|
+
else:
|
|
208
|
+
defaults = generate_default_rich_block(theme)
|
|
209
|
+
rich_props = theme.get("rich", {})
|
|
210
|
+
final_styles = {
|
|
211
|
+
key: rich_props.get(key, defaults[key]) for key in defaults
|
|
212
|
+
}
|
|
213
|
+
# Ensure tuple for padding properties.
|
|
214
|
+
final_styles["panel_padding"] = tuple(final_styles["panel_padding"])
|
|
215
|
+
if "table_padding" in final_styles:
|
|
216
|
+
final_styles["table_padding"] = tuple(final_styles["table_padding"])
|
|
217
|
+
# Resolve tokens.
|
|
218
|
+
if theme is not None:
|
|
219
|
+
for key, value in final_styles.items():
|
|
220
|
+
if isinstance(value, str):
|
|
221
|
+
final_styles[key] = resolve_style_string(value, theme)
|
|
222
|
+
return final_styles
|
|
223
|
+
|
|
224
|
+
|
|
225
|
+
def create_rich_renderable(
|
|
226
|
+
value: Any,
|
|
227
|
+
level: int = 0,
|
|
228
|
+
theme: dict | None = None,
|
|
229
|
+
styles: dict[str, Any] | None = None,
|
|
230
|
+
) -> Any:
|
|
231
|
+
"""Recursively creates a Rich renderable.
|
|
232
|
+
|
|
233
|
+
- If value is a dict, renders it as a Table.
|
|
234
|
+
- If a list/tuple, renders each item.
|
|
235
|
+
- Otherwise, returns the string representation.
|
|
236
|
+
"""
|
|
237
|
+
if styles is None:
|
|
238
|
+
styles = get_default_styles(theme)
|
|
239
|
+
|
|
240
|
+
if isinstance(value, dict):
|
|
241
|
+
box_style = (
|
|
242
|
+
getattr(box, styles["table_box"])
|
|
243
|
+
if isinstance(styles["table_box"], str)
|
|
244
|
+
else styles["table_box"]
|
|
245
|
+
)
|
|
246
|
+
table_kwargs = {
|
|
247
|
+
"show_header": True,
|
|
248
|
+
"header_style": styles["table_header_style"],
|
|
249
|
+
"title": f"Subtable (Level {level})" if level > 0 else None,
|
|
250
|
+
"title_style": styles["table_title_style"],
|
|
251
|
+
"border_style": styles["table_border_style"],
|
|
252
|
+
"show_lines": styles["table_show_lines"],
|
|
253
|
+
"box": box_style,
|
|
254
|
+
"row_styles": styles["table_row_styles"],
|
|
255
|
+
"safe_box": styles.get("table_safe_box"),
|
|
256
|
+
"padding": styles.get("table_padding"),
|
|
257
|
+
"collapse_padding": styles.get("table_collapse_padding"),
|
|
258
|
+
"pad_edge": styles.get("table_pad_edge"),
|
|
259
|
+
"expand": styles.get("table_expand"),
|
|
260
|
+
"show_footer": styles.get("table_show_footer"),
|
|
261
|
+
"show_edge": styles.get("table_show_edge"),
|
|
262
|
+
"leading": styles.get("table_leading"),
|
|
263
|
+
"style": styles.get("table_style"),
|
|
264
|
+
"footer_style": styles.get("table_footer_style"),
|
|
265
|
+
"caption": styles.get("table_caption"),
|
|
266
|
+
"caption_style": styles.get("table_caption_style"),
|
|
267
|
+
"title_justify": styles.get("table_title_justify"),
|
|
268
|
+
"caption_justify": styles.get("table_caption_justify"),
|
|
269
|
+
"highlight": styles.get("table_highlight"),
|
|
270
|
+
}
|
|
271
|
+
table = Table(**table_kwargs)
|
|
272
|
+
table.add_column("Key", style=styles["column_output"])
|
|
273
|
+
table.add_column("Value", style=styles["column_value"])
|
|
274
|
+
for k, v in value.items():
|
|
275
|
+
table.add_row(
|
|
276
|
+
str(k), create_rich_renderable(v, level + 1, theme, styles)
|
|
277
|
+
)
|
|
278
|
+
return table
|
|
279
|
+
|
|
280
|
+
elif isinstance(value, (list, tuple)):
|
|
281
|
+
if all(isinstance(item, dict) for item in value):
|
|
282
|
+
sub_tables = []
|
|
283
|
+
for i, item in enumerate(value):
|
|
284
|
+
sub_tables.append(f"[bold]Item {i + 1}[/bold]")
|
|
285
|
+
sub_tables.append(
|
|
286
|
+
create_rich_renderable(item, level + 1, theme, styles)
|
|
287
|
+
)
|
|
288
|
+
return Group(*sub_tables)
|
|
289
|
+
else:
|
|
290
|
+
rendered_items = [
|
|
291
|
+
create_rich_renderable(item, level + 1, theme, styles)
|
|
292
|
+
for item in value
|
|
293
|
+
]
|
|
294
|
+
if all(isinstance(item, str) for item in rendered_items):
|
|
295
|
+
return "\n".join(rendered_items)
|
|
296
|
+
else:
|
|
297
|
+
return Group(*rendered_items)
|
|
298
|
+
else:
|
|
299
|
+
if isinstance(value, str) and "\n" in value:
|
|
300
|
+
return f"\n{value}\n"
|
|
301
|
+
return str(value)
|
|
302
|
+
|
|
303
|
+
|
|
304
|
+
# --- Theme Builder Functions --- #
|
|
305
|
+
|
|
306
|
+
|
|
307
|
+
def load_theme_files(theme_dir: pathlib.Path) -> list[pathlib.Path]:
|
|
308
|
+
"""Return a list of .toml theme files in the given directory."""
|
|
309
|
+
return list(theme_dir.glob("*.toml"))
|
|
310
|
+
|
|
311
|
+
|
|
312
|
+
def display_color_palette(theme: dict) -> None:
|
|
313
|
+
"""Display the color palette from a theme's [colors] sections with a color preview."""
|
|
314
|
+
console = Console()
|
|
315
|
+
palette_table = Table(
|
|
316
|
+
title="Color Palette", show_header=True, header_style="bold"
|
|
317
|
+
)
|
|
318
|
+
palette_table.add_column("Section", style="bold")
|
|
319
|
+
palette_table.add_column("Key", style="italic")
|
|
320
|
+
palette_table.add_column("Value", style="bold")
|
|
321
|
+
palette_table.add_column("Preview", justify="center")
|
|
322
|
+
|
|
323
|
+
# Iterate over the colors in each section.
|
|
324
|
+
for section, colors in theme.get("colors", {}).items():
|
|
325
|
+
for key, value in colors.items():
|
|
326
|
+
# Create a Text object with a fixed-width string (here, six spaces)
|
|
327
|
+
# styled with a background color of the actual color value.
|
|
328
|
+
preview = Text(" ", style=f"on {value}")
|
|
329
|
+
palette_table.add_row(section, key, value, preview)
|
|
330
|
+
|
|
331
|
+
console.print(palette_table)
|
|
332
|
+
|
|
333
|
+
|
|
334
|
+
def generate_sample_rich_blocks(
|
|
335
|
+
chosen_theme: dict, count: int
|
|
336
|
+
) -> list[dict[str, Any]]:
|
|
337
|
+
"""Generate a list of sample rich blocks (randomized layout) using the chosen theme's colors."""
|
|
338
|
+
samples = []
|
|
339
|
+
for _ in range(count):
|
|
340
|
+
samples.append(generate_default_rich_block(chosen_theme))
|
|
341
|
+
return samples
|
|
342
|
+
|
|
343
|
+
|
|
344
|
+
def generate_sample_table(sample_theme: dict, dummy_data: dict) -> Panel:
|
|
345
|
+
"""Generate a sample table using the given theme dictionary (which includes a [rich] block)
|
|
346
|
+
and some dummy data.
|
|
347
|
+
"""
|
|
348
|
+
# Here we use our create_rich_renderable to build a table for dummy_data.
|
|
349
|
+
# For simplicity, we create our own panel.
|
|
350
|
+
styles = get_default_styles(sample_theme)
|
|
351
|
+
# Build a basic table (using our earlier functions)
|
|
352
|
+
table = create_rich_renderable(
|
|
353
|
+
dummy_data, theme=sample_theme, styles=styles
|
|
354
|
+
)
|
|
355
|
+
return Panel(
|
|
356
|
+
table,
|
|
357
|
+
title="Sample Table",
|
|
358
|
+
title_align=styles["panel_title_align"],
|
|
359
|
+
border_style=styles["panel_border_style"],
|
|
360
|
+
padding=styles["panel_padding"],
|
|
361
|
+
style=styles["panel_style"],
|
|
362
|
+
)
|
|
363
|
+
|
|
364
|
+
|
|
365
|
+
def save_theme(theme: dict, filename: pathlib.Path) -> None:
|
|
366
|
+
"""Save the given theme dictionary to the specified TOML file."""
|
|
367
|
+
with open(filename, "w") as f:
|
|
368
|
+
toml.dump(theme, f)
|
|
369
|
+
|
|
370
|
+
|
|
371
|
+
# --- Main Interactive Loop --- #
|
|
372
|
+
|
|
373
|
+
|
|
374
|
+
def main():
|
|
375
|
+
console = Console(force_terminal=True, color_system="truecolor")
|
|
376
|
+
themes_dir = pathlib.Path(__file__).parent.parent.parent.parent / "themes"
|
|
377
|
+
theme_files = load_theme_files(themes_dir)
|
|
378
|
+
|
|
379
|
+
if not theme_files:
|
|
380
|
+
console.print("[red]No theme files found in the themes folder.[/red]")
|
|
381
|
+
return
|
|
382
|
+
|
|
383
|
+
# Ask the user: load all themes or N random themes?
|
|
384
|
+
console.print("[bold]Theme Builder[/bold]")
|
|
385
|
+
choice = console.input(
|
|
386
|
+
"Load [bold](a)ll[/bold] themes or [bold](n)[/bold] random ones? (a/n): "
|
|
387
|
+
)
|
|
388
|
+
if choice.lower() == "n":
|
|
389
|
+
n = console.input("How many random themes? ")
|
|
390
|
+
try:
|
|
391
|
+
n = int(n)
|
|
392
|
+
except ValueError:
|
|
393
|
+
n = len(theme_files)
|
|
394
|
+
theme_files = random.sample(theme_files, min(n, len(theme_files)))
|
|
395
|
+
|
|
396
|
+
# Display palettes for each theme file.
|
|
397
|
+
console.print("\n[underline]Available Color Palettes:[/underline]")
|
|
398
|
+
palettes = []
|
|
399
|
+
for idx, tf in enumerate(theme_files):
|
|
400
|
+
theme_dict = load_theme_from_file(str(tf))
|
|
401
|
+
palettes.append((tf, theme_dict))
|
|
402
|
+
console.print(f"\n[bold]Theme #{idx} - {tf.name}[/bold]")
|
|
403
|
+
display_color_palette(theme_dict)
|
|
404
|
+
|
|
405
|
+
# Let the user choose a palette by index.
|
|
406
|
+
sel = console.input("\nEnter the number of the palette to use: ")
|
|
407
|
+
try:
|
|
408
|
+
sel = int(sel)
|
|
409
|
+
chosen_theme = palettes[sel][1]
|
|
410
|
+
except (ValueError, IndexError):
|
|
411
|
+
console.print("[red]Invalid selection. Exiting.[/red]")
|
|
412
|
+
return
|
|
413
|
+
|
|
414
|
+
console.print("\n[underline]Selected Palette:[/underline]")
|
|
415
|
+
display_color_palette(chosen_theme)
|
|
416
|
+
|
|
417
|
+
# Ask the user how many sample tables to generate.
|
|
418
|
+
count = console.input("\nHow many sample tables to generate? (default 3): ")
|
|
419
|
+
try:
|
|
420
|
+
count = int(count)
|
|
421
|
+
except ValueError:
|
|
422
|
+
count = 3
|
|
423
|
+
|
|
424
|
+
# Generate sample rich blocks from the chosen theme.
|
|
425
|
+
sample_rich_blocks = generate_sample_rich_blocks(chosen_theme, count)
|
|
426
|
+
|
|
427
|
+
# For each sample, create a new theme dict that uses the chosen palette and the sample rich block.
|
|
428
|
+
dummy_data = {
|
|
429
|
+
"Agent": "Test Agent",
|
|
430
|
+
"Status": "Running",
|
|
431
|
+
"Metrics": {
|
|
432
|
+
"CPU": "20%",
|
|
433
|
+
"Memory": "512MB",
|
|
434
|
+
"Nested": {"value1": 1, "value2": 2},
|
|
435
|
+
},
|
|
436
|
+
"Logs": [
|
|
437
|
+
"Initialization complete",
|
|
438
|
+
"Running process...",
|
|
439
|
+
{"Step": "Completed", "Time": "2025-02-07T12:00:00Z"},
|
|
440
|
+
],
|
|
441
|
+
}
|
|
442
|
+
|
|
443
|
+
samples = []
|
|
444
|
+
for i, rich_block in enumerate(sample_rich_blocks):
|
|
445
|
+
# Build a sample theme: copy the chosen theme and override its [rich] block.
|
|
446
|
+
sample_theme = dict(
|
|
447
|
+
chosen_theme
|
|
448
|
+
) # shallow copy (good enough if colors remain unchanged)
|
|
449
|
+
sample_theme["rich"] = rich_block
|
|
450
|
+
sample_table = generate_sample_table(sample_theme, dummy_data)
|
|
451
|
+
samples.append((sample_theme, sample_table))
|
|
452
|
+
console.print(f"\n[bold]Sample Table #{i}[/bold]")
|
|
453
|
+
console.print(sample_table)
|
|
454
|
+
|
|
455
|
+
# Let the user choose one sample or regenerate.
|
|
456
|
+
sel2 = console.input(
|
|
457
|
+
"\nEnter the number of the sample table you like, or type [bold]r[/bold] to regenerate: "
|
|
458
|
+
)
|
|
459
|
+
if sel2.lower() == "r":
|
|
460
|
+
console.print("Regenerating samples...")
|
|
461
|
+
main() # restart the builder
|
|
462
|
+
return
|
|
463
|
+
try:
|
|
464
|
+
sel2 = int(sel2)
|
|
465
|
+
chosen_sample_theme = samples[sel2][0]
|
|
466
|
+
except (ValueError, IndexError):
|
|
467
|
+
console.print("[red]Invalid selection. Exiting.[/red]")
|
|
468
|
+
return
|
|
469
|
+
|
|
470
|
+
# Ask for file name to save the chosen theme.
|
|
471
|
+
filename = console.input(
|
|
472
|
+
"\nEnter a filename to save the chosen theme (e.g. mytheme.toml): "
|
|
473
|
+
)
|
|
474
|
+
save_path = themes_dir / filename
|
|
475
|
+
save_theme(chosen_sample_theme, save_path)
|
|
476
|
+
console.print(f"\n[green]Theme saved as {save_path}.[/green]")
|
|
477
|
+
|
|
478
|
+
|
|
479
|
+
if __name__ == "__main__":
|
|
480
|
+
main()
|