flock-core 0.4.542__py3-none-any.whl → 0.5.0__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 +12 -217
- flock/agent.py +1079 -0
- flock/api/themes.py +71 -0
- flock/artifacts.py +86 -0
- flock/cli.py +147 -0
- flock/components.py +189 -0
- flock/dashboard/__init__.py +30 -0
- flock/dashboard/collector.py +559 -0
- flock/dashboard/events.py +188 -0
- flock/dashboard/graph_builder.py +563 -0
- flock/dashboard/launcher.py +235 -0
- flock/dashboard/models/graph.py +156 -0
- flock/dashboard/service.py +991 -0
- flock/dashboard/static_v2/assets/index-DFRnI_mt.js +111 -0
- flock/dashboard/static_v2/assets/index-fPLNdmp1.css +1 -0
- flock/dashboard/static_v2/index.html +13 -0
- flock/dashboard/websocket.py +246 -0
- flock/engines/__init__.py +6 -0
- flock/engines/dspy_engine.py +932 -0
- flock/examples.py +131 -0
- flock/frontend/README.md +778 -0
- flock/frontend/docs/DESIGN_SYSTEM.md +1980 -0
- flock/frontend/index.html +12 -0
- flock/frontend/package-lock.json +4337 -0
- flock/frontend/package.json +48 -0
- flock/frontend/src/App.tsx +139 -0
- flock/frontend/src/__tests__/integration/graph-snapshot.test.tsx +647 -0
- flock/frontend/src/__tests__/integration/indexeddb-persistence.test.tsx +699 -0
- flock/frontend/src/components/common/BuildInfo.tsx +39 -0
- flock/frontend/src/components/common/EmptyState.module.css +115 -0
- flock/frontend/src/components/common/EmptyState.tsx +128 -0
- flock/frontend/src/components/common/ErrorBoundary.module.css +169 -0
- flock/frontend/src/components/common/ErrorBoundary.tsx +118 -0
- flock/frontend/src/components/common/KeyboardShortcutsDialog.css +251 -0
- flock/frontend/src/components/common/KeyboardShortcutsDialog.tsx +151 -0
- flock/frontend/src/components/common/LoadingSpinner.module.css +97 -0
- flock/frontend/src/components/common/LoadingSpinner.tsx +29 -0
- flock/frontend/src/components/controls/PublishControl.css +547 -0
- flock/frontend/src/components/controls/PublishControl.test.tsx +543 -0
- flock/frontend/src/components/controls/PublishControl.tsx +432 -0
- flock/frontend/src/components/details/DetailWindowContainer.tsx +58 -0
- flock/frontend/src/components/details/LiveOutputTab.test.tsx +792 -0
- flock/frontend/src/components/details/LiveOutputTab.tsx +220 -0
- flock/frontend/src/components/details/MessageDetailWindow.tsx +439 -0
- flock/frontend/src/components/details/MessageHistoryTab.tsx +374 -0
- flock/frontend/src/components/details/NodeDetailWindow.test.tsx +501 -0
- flock/frontend/src/components/details/NodeDetailWindow.tsx +218 -0
- flock/frontend/src/components/details/RunStatusTab.tsx +348 -0
- flock/frontend/src/components/details/tabs.test.tsx +1015 -0
- flock/frontend/src/components/filters/ArtifactTypeFilter.tsx +21 -0
- flock/frontend/src/components/filters/CorrelationIDFilter.module.css +102 -0
- flock/frontend/src/components/filters/CorrelationIDFilter.test.tsx +197 -0
- flock/frontend/src/components/filters/CorrelationIDFilter.tsx +121 -0
- flock/frontend/src/components/filters/FilterFlyout.module.css +104 -0
- flock/frontend/src/components/filters/FilterFlyout.tsx +80 -0
- flock/frontend/src/components/filters/FilterPills.module.css +220 -0
- flock/frontend/src/components/filters/FilterPills.test.tsx +189 -0
- flock/frontend/src/components/filters/FilterPills.tsx +143 -0
- flock/frontend/src/components/filters/ProducerFilter.tsx +21 -0
- flock/frontend/src/components/filters/SavedFiltersControl.module.css +60 -0
- flock/frontend/src/components/filters/SavedFiltersControl.test.tsx +158 -0
- flock/frontend/src/components/filters/SavedFiltersControl.tsx +159 -0
- flock/frontend/src/components/filters/TagFilter.tsx +21 -0
- flock/frontend/src/components/filters/TimeRangeFilter.module.css +115 -0
- flock/frontend/src/components/filters/TimeRangeFilter.test.tsx +154 -0
- flock/frontend/src/components/filters/TimeRangeFilter.tsx +110 -0
- flock/frontend/src/components/filters/VisibilityFilter.tsx +21 -0
- flock/frontend/src/components/graph/AgentNode.test.tsx +77 -0
- flock/frontend/src/components/graph/AgentNode.tsx +324 -0
- flock/frontend/src/components/graph/GraphCanvas.tsx +613 -0
- flock/frontend/src/components/graph/MessageFlowEdge.tsx +128 -0
- flock/frontend/src/components/graph/MessageNode.test.tsx +64 -0
- flock/frontend/src/components/graph/MessageNode.tsx +129 -0
- flock/frontend/src/components/graph/MiniMap.tsx +47 -0
- flock/frontend/src/components/graph/TransformEdge.tsx +123 -0
- flock/frontend/src/components/layout/DashboardLayout.css +420 -0
- flock/frontend/src/components/layout/DashboardLayout.tsx +287 -0
- flock/frontend/src/components/layout/Header.module.css +88 -0
- flock/frontend/src/components/layout/Header.tsx +52 -0
- flock/frontend/src/components/modules/HistoricalArtifactsModule.module.css +288 -0
- flock/frontend/src/components/modules/HistoricalArtifactsModule.tsx +450 -0
- flock/frontend/src/components/modules/HistoricalArtifactsModuleWrapper.tsx +13 -0
- flock/frontend/src/components/modules/JsonAttributeRenderer.tsx +140 -0
- flock/frontend/src/components/modules/ModuleRegistry.test.ts +333 -0
- flock/frontend/src/components/modules/ModuleRegistry.ts +93 -0
- flock/frontend/src/components/modules/ModuleWindow.tsx +223 -0
- flock/frontend/src/components/modules/TraceModuleJaeger.tsx +1971 -0
- flock/frontend/src/components/modules/TraceModuleJaegerWrapper.tsx +13 -0
- flock/frontend/src/components/modules/registerModules.ts +29 -0
- flock/frontend/src/components/settings/AdvancedSettings.tsx +175 -0
- flock/frontend/src/components/settings/AppearanceSettings.tsx +185 -0
- flock/frontend/src/components/settings/GraphSettings.tsx +110 -0
- flock/frontend/src/components/settings/MultiSelect.tsx +235 -0
- flock/frontend/src/components/settings/SettingsPanel.css +327 -0
- flock/frontend/src/components/settings/SettingsPanel.tsx +131 -0
- flock/frontend/src/components/settings/ThemeSelector.tsx +298 -0
- flock/frontend/src/components/settings/TracingSettings.tsx +404 -0
- flock/frontend/src/hooks/useKeyboardShortcuts.ts +148 -0
- flock/frontend/src/hooks/useModulePersistence.test.ts +442 -0
- flock/frontend/src/hooks/useModulePersistence.ts +154 -0
- flock/frontend/src/hooks/useModules.ts +157 -0
- flock/frontend/src/hooks/usePersistence.ts +141 -0
- flock/frontend/src/main.tsx +13 -0
- flock/frontend/src/services/api.ts +337 -0
- flock/frontend/src/services/graphService.test.ts +330 -0
- flock/frontend/src/services/graphService.ts +75 -0
- flock/frontend/src/services/indexeddb.test.ts +793 -0
- flock/frontend/src/services/indexeddb.ts +848 -0
- flock/frontend/src/services/layout.test.ts +437 -0
- flock/frontend/src/services/layout.ts +357 -0
- flock/frontend/src/services/themeApplicator.ts +140 -0
- flock/frontend/src/services/themeService.ts +77 -0
- flock/frontend/src/services/websocket.ts +650 -0
- flock/frontend/src/store/filterStore.test.ts +250 -0
- flock/frontend/src/store/filterStore.ts +272 -0
- flock/frontend/src/store/graphStore.test.ts +570 -0
- flock/frontend/src/store/graphStore.ts +462 -0
- flock/frontend/src/store/moduleStore.test.ts +253 -0
- flock/frontend/src/store/moduleStore.ts +75 -0
- flock/frontend/src/store/settingsStore.ts +188 -0
- flock/frontend/src/store/streamStore.ts +68 -0
- flock/frontend/src/store/uiStore.test.ts +54 -0
- flock/frontend/src/store/uiStore.ts +122 -0
- flock/frontend/src/store/wsStore.ts +34 -0
- flock/frontend/src/styles/index.css +15 -0
- flock/frontend/src/styles/scrollbar.css +47 -0
- flock/frontend/src/styles/variables.css +488 -0
- flock/frontend/src/test/setup.ts +1 -0
- flock/frontend/src/types/filters.ts +47 -0
- flock/frontend/src/types/graph.ts +95 -0
- flock/frontend/src/types/modules.ts +10 -0
- flock/frontend/src/types/theme.ts +55 -0
- flock/frontend/src/utils/artifacts.ts +24 -0
- flock/frontend/src/utils/mockData.ts +98 -0
- flock/frontend/src/utils/performance.ts +16 -0
- flock/frontend/src/vite-env.d.ts +17 -0
- flock/frontend/tsconfig.json +27 -0
- flock/frontend/tsconfig.node.json +11 -0
- flock/frontend/vite.config.ts +25 -0
- flock/frontend/vitest.config.ts +11 -0
- flock/{core/util → helper}/cli_helper.py +9 -5
- flock/{core/logging → logging}/__init__.py +2 -3
- flock/logging/auto_trace.py +159 -0
- flock/{core/logging → logging}/formatters/enum_builder.py +3 -4
- flock/{core/logging → logging}/formatters/theme_builder.py +19 -44
- flock/{core/logging → logging}/formatters/themed_formatter.py +69 -107
- flock/{core/logging → logging}/logging.py +78 -61
- flock/{core/logging → logging}/telemetry.py +66 -26
- flock/{core/logging → logging}/telemetry_exporter/base_exporter.py +2 -2
- flock/logging/telemetry_exporter/duckdb_exporter.py +216 -0
- flock/{core/logging → logging}/telemetry_exporter/file_exporter.py +13 -10
- flock/{core/logging → logging}/telemetry_exporter/sqlite_exporter.py +2 -3
- flock/logging/trace_and_logged.py +304 -0
- flock/mcp/__init__.py +91 -0
- flock/{core/mcp/mcp_client.py → mcp/client.py} +131 -158
- flock/{core/mcp/mcp_config.py → mcp/config.py} +86 -132
- flock/mcp/manager.py +286 -0
- flock/mcp/servers/sse/__init__.py +1 -1
- flock/mcp/servers/sse/flock_sse_server.py +16 -58
- flock/mcp/servers/stdio/__init__.py +1 -1
- flock/mcp/servers/stdio/flock_stdio_server.py +13 -53
- flock/mcp/servers/streamable_http/flock_streamable_http_server.py +22 -67
- flock/mcp/servers/websockets/flock_websocket_server.py +12 -45
- flock/{core/mcp/flock_mcp_tool_base.py → mcp/tool.py} +24 -78
- flock/mcp/types/__init__.py +42 -0
- flock/{core/mcp → mcp}/types/callbacks.py +12 -15
- flock/{core/mcp → mcp}/types/factories.py +7 -6
- flock/{core/mcp → mcp}/types/handlers.py +13 -18
- flock/{core/mcp → mcp}/types/types.py +70 -74
- flock/{core/mcp → mcp}/util/helpers.py +3 -3
- flock/orchestrator.py +970 -0
- flock/registry.py +148 -0
- flock/runtime.py +262 -0
- flock/service.py +277 -0
- flock/store.py +1214 -0
- flock/subscription.py +111 -0
- flock/themes/andromeda.toml +1 -1
- flock/themes/apple-system-colors.toml +1 -1
- flock/themes/arcoiris.toml +1 -1
- flock/themes/atomonelight.toml +1 -1
- flock/themes/ayu copy.toml +1 -1
- flock/themes/ayu-light.toml +1 -1
- flock/themes/belafonte-day.toml +1 -1
- flock/themes/belafonte-night.toml +1 -1
- flock/themes/blulocodark.toml +1 -1
- flock/themes/breeze.toml +1 -1
- flock/themes/broadcast.toml +1 -1
- flock/themes/brogrammer.toml +1 -1
- flock/themes/builtin-dark.toml +1 -1
- flock/themes/builtin-pastel-dark.toml +1 -1
- flock/themes/catppuccin-latte.toml +1 -1
- flock/themes/catppuccin-macchiato.toml +1 -1
- flock/themes/catppuccin-mocha.toml +1 -1
- flock/themes/cga.toml +1 -1
- flock/themes/chalk.toml +1 -1
- flock/themes/ciapre.toml +1 -1
- flock/themes/coffee-theme.toml +1 -1
- flock/themes/cyberpunkscarletprotocol.toml +1 -1
- flock/themes/dark+.toml +1 -1
- flock/themes/darkermatrix.toml +1 -1
- flock/themes/darkmatrix.toml +2 -2
- flock/themes/darkside.toml +1 -1
- flock/themes/deep.toml +2 -2
- flock/themes/desert.toml +1 -1
- flock/themes/django.toml +1 -1
- flock/themes/djangosmooth.toml +1 -1
- flock/themes/doomone.toml +1 -1
- flock/themes/dotgov.toml +1 -1
- flock/themes/dracula+.toml +1 -1
- flock/themes/duckbones.toml +1 -1
- flock/themes/encom.toml +1 -1
- flock/themes/espresso.toml +1 -1
- flock/themes/everblush.toml +1 -1
- flock/themes/fairyfloss.toml +1 -1
- flock/themes/fideloper.toml +1 -1
- flock/themes/fishtank.toml +1 -1
- flock/themes/flexoki-light.toml +1 -1
- flock/themes/floraverse.toml +1 -1
- flock/themes/framer.toml +1 -1
- flock/themes/galizur.toml +1 -1
- flock/themes/github.toml +1 -1
- flock/themes/grass.toml +1 -1
- flock/themes/grey-green.toml +1 -1
- flock/themes/gruvboxlight.toml +1 -1
- flock/themes/guezwhoz.toml +1 -1
- flock/themes/harper.toml +1 -1
- flock/themes/hax0r-blue.toml +1 -1
- flock/themes/hopscotch.256.toml +1 -1
- flock/themes/ic-green-ppl.toml +1 -1
- flock/themes/iceberg-dark.toml +1 -1
- flock/themes/japanesque.toml +1 -1
- flock/themes/jubi.toml +1 -1
- flock/themes/kibble.toml +1 -1
- flock/themes/kolorit.toml +1 -1
- flock/themes/kurokula.toml +1 -1
- flock/themes/materialdesigncolors.toml +1 -1
- flock/themes/matrix.toml +1 -1
- flock/themes/mellifluous.toml +1 -1
- flock/themes/midnight-in-mojave.toml +1 -1
- flock/themes/monokai-remastered.toml +1 -1
- flock/themes/monokai-soda.toml +1 -1
- flock/themes/neon.toml +1 -1
- flock/themes/neopolitan.toml +5 -5
- flock/themes/nord-light.toml +1 -1
- flock/themes/ocean.toml +1 -1
- flock/themes/onehalfdark.toml +1 -1
- flock/themes/onehalflight.toml +1 -1
- flock/themes/palenighthc.toml +1 -1
- flock/themes/paulmillr.toml +1 -1
- flock/themes/pencildark.toml +1 -1
- flock/themes/pnevma.toml +1 -1
- flock/themes/purple-rain.toml +1 -1
- flock/themes/purplepeter.toml +1 -1
- flock/themes/raycast-dark.toml +1 -1
- flock/themes/red-sands.toml +1 -1
- flock/themes/relaxed.toml +1 -1
- flock/themes/retro.toml +1 -1
- flock/themes/rose-pine.toml +1 -1
- flock/themes/royal.toml +1 -1
- flock/themes/ryuuko.toml +1 -1
- flock/themes/sakura.toml +1 -1
- flock/themes/scarlet-protocol.toml +1 -1
- flock/themes/seoulbones-dark.toml +1 -1
- flock/themes/shades-of-purple.toml +1 -1
- flock/themes/smyck.toml +1 -1
- flock/themes/softserver.toml +1 -1
- flock/themes/solarized-darcula.toml +1 -1
- flock/themes/square.toml +1 -1
- flock/themes/sugarplum.toml +1 -1
- flock/themes/thayer-bright.toml +1 -1
- flock/themes/tokyonight.toml +1 -1
- flock/themes/tomorrow.toml +1 -1
- flock/themes/ubuntu.toml +1 -1
- flock/themes/ultradark.toml +1 -1
- flock/themes/ultraviolent.toml +1 -1
- flock/themes/unikitty.toml +1 -1
- flock/themes/urple.toml +1 -1
- flock/themes/vesper.toml +1 -1
- flock/themes/vimbones.toml +1 -1
- flock/themes/wildcherry.toml +1 -1
- flock/themes/wilmersdorf.toml +1 -1
- flock/themes/wryan.toml +1 -1
- flock/themes/xcodedarkhc.toml +1 -1
- flock/themes/xcodelight.toml +1 -1
- flock/themes/zenbones-light.toml +1 -1
- flock/themes/zenwritten-dark.toml +1 -1
- flock/utilities.py +301 -0
- flock/utility/output_utility_component.py +226 -0
- flock/visibility.py +107 -0
- flock_core-0.5.0.dist-info/METADATA +964 -0
- flock_core-0.5.0.dist-info/RECORD +525 -0
- flock_core-0.5.0.dist-info/entry_points.txt +2 -0
- {flock_core-0.4.542.dist-info → flock_core-0.5.0.dist-info}/licenses/LICENSE +1 -1
- flock/adapter/__init__.py +0 -14
- flock/adapter/azure_adapter.py +0 -68
- flock/adapter/chroma_adapter.py +0 -73
- flock/adapter/faiss_adapter.py +0 -97
- flock/adapter/pinecone_adapter.py +0 -51
- flock/adapter/vector_base.py +0 -47
- flock/cli/assets/release_notes.md +0 -140
- flock/cli/config.py +0 -8
- flock/cli/constants.py +0 -36
- flock/cli/create_agent.py +0 -1
- flock/cli/create_flock.py +0 -280
- flock/cli/execute_flock.py +0 -620
- flock/cli/load_agent.py +0 -1
- flock/cli/load_examples.py +0 -1
- flock/cli/load_flock.py +0 -192
- flock/cli/load_release_notes.py +0 -20
- flock/cli/loaded_flock_cli.py +0 -254
- flock/cli/manage_agents.py +0 -459
- flock/cli/registry_management.py +0 -889
- flock/cli/runner.py +0 -41
- flock/cli/settings.py +0 -857
- flock/cli/utils.py +0 -135
- flock/cli/view_results.py +0 -29
- flock/cli/yaml_editor.py +0 -396
- flock/config.py +0 -56
- flock/core/__init__.py +0 -44
- flock/core/api/__init__.py +0 -10
- flock/core/api/custom_endpoint.py +0 -45
- flock/core/api/endpoints.py +0 -262
- flock/core/api/main.py +0 -162
- flock/core/api/models.py +0 -101
- flock/core/api/run_store.py +0 -224
- flock/core/api/runner.py +0 -44
- flock/core/api/service.py +0 -214
- flock/core/config/flock_agent_config.py +0 -11
- flock/core/config/scheduled_agent_config.py +0 -40
- flock/core/context/context.py +0 -214
- flock/core/context/context_manager.py +0 -40
- flock/core/context/context_vars.py +0 -11
- flock/core/evaluation/utils.py +0 -395
- flock/core/execution/batch_executor.py +0 -369
- flock/core/execution/evaluation_executor.py +0 -438
- flock/core/execution/local_executor.py +0 -31
- flock/core/execution/opik_executor.py +0 -103
- flock/core/execution/temporal_executor.py +0 -166
- flock/core/flock.py +0 -1003
- flock/core/flock_agent.py +0 -1258
- flock/core/flock_evaluator.py +0 -60
- flock/core/flock_factory.py +0 -513
- flock/core/flock_module.py +0 -207
- flock/core/flock_registry.py +0 -702
- flock/core/flock_router.py +0 -83
- flock/core/flock_scheduler.py +0 -166
- flock/core/flock_server_manager.py +0 -136
- flock/core/interpreter/python_interpreter.py +0 -689
- flock/core/logging/live_capture.py +0 -137
- flock/core/logging/trace_and_logged.py +0 -59
- flock/core/mcp/__init__.py +0 -1
- flock/core/mcp/flock_mcp_server.py +0 -640
- flock/core/mcp/mcp_client_manager.py +0 -201
- flock/core/mcp/types/__init__.py +0 -1
- flock/core/mixin/dspy_integration.py +0 -445
- flock/core/mixin/prompt_parser.py +0 -125
- flock/core/serialization/__init__.py +0 -13
- flock/core/serialization/callable_registry.py +0 -52
- flock/core/serialization/flock_serializer.py +0 -854
- flock/core/serialization/json_encoder.py +0 -41
- flock/core/serialization/secure_serializer.py +0 -175
- flock/core/serialization/serializable.py +0 -342
- flock/core/serialization/serialization_utils.py +0 -409
- flock/core/util/file_path_utils.py +0 -223
- flock/core/util/hydrator.py +0 -309
- flock/core/util/input_resolver.py +0 -141
- flock/core/util/loader.py +0 -59
- flock/core/util/splitter.py +0 -219
- flock/di.py +0 -41
- flock/evaluators/__init__.py +0 -1
- flock/evaluators/declarative/__init__.py +0 -1
- flock/evaluators/declarative/declarative_evaluator.py +0 -217
- flock/evaluators/memory/memory_evaluator.py +0 -90
- flock/evaluators/test/test_case_evaluator.py +0 -38
- flock/evaluators/zep/zep_evaluator.py +0 -59
- flock/modules/__init__.py +0 -1
- flock/modules/assertion/__init__.py +0 -1
- flock/modules/assertion/assertion_module.py +0 -286
- flock/modules/callback/__init__.py +0 -1
- flock/modules/callback/callback_module.py +0 -91
- flock/modules/enterprise_memory/README.md +0 -99
- flock/modules/enterprise_memory/enterprise_memory_module.py +0 -526
- flock/modules/mem0/__init__.py +0 -1
- flock/modules/mem0/mem0_module.py +0 -126
- flock/modules/mem0_async/__init__.py +0 -1
- flock/modules/mem0_async/async_mem0_module.py +0 -126
- flock/modules/memory/__init__.py +0 -1
- flock/modules/memory/memory_module.py +0 -429
- flock/modules/memory/memory_parser.py +0 -125
- flock/modules/memory/memory_storage.py +0 -736
- flock/modules/output/__init__.py +0 -1
- flock/modules/output/output_module.py +0 -196
- flock/modules/performance/__init__.py +0 -1
- flock/modules/performance/metrics_module.py +0 -678
- flock/modules/zep/__init__.py +0 -1
- flock/modules/zep/zep_module.py +0 -192
- flock/platform/docker_tools.py +0 -49
- flock/platform/jaeger_install.py +0 -86
- flock/routers/__init__.py +0 -1
- flock/routers/agent/__init__.py +0 -1
- flock/routers/agent/agent_router.py +0 -236
- flock/routers/agent/handoff_agent.py +0 -58
- flock/routers/conditional/conditional_router.py +0 -486
- flock/routers/default/__init__.py +0 -1
- flock/routers/default/default_router.py +0 -80
- flock/routers/feedback/feedback_router.py +0 -114
- flock/routers/list_generator/list_generator_router.py +0 -166
- flock/routers/llm/__init__.py +0 -1
- flock/routers/llm/llm_router.py +0 -365
- flock/tools/__init__.py +0 -0
- flock/tools/azure_tools.py +0 -781
- flock/tools/code_tools.py +0 -167
- flock/tools/file_tools.py +0 -149
- flock/tools/github_tools.py +0 -157
- flock/tools/markdown_tools.py +0 -205
- flock/tools/system_tools.py +0 -9
- flock/tools/text_tools.py +0 -810
- flock/tools/web_tools.py +0 -92
- flock/tools/zendesk_tools.py +0 -501
- flock/webapp/__init__.py +0 -1
- flock/webapp/app/__init__.py +0 -0
- flock/webapp/app/api/__init__.py +0 -0
- flock/webapp/app/api/agent_management.py +0 -237
- flock/webapp/app/api/execution.py +0 -503
- flock/webapp/app/api/flock_management.py +0 -125
- flock/webapp/app/api/registry_viewer.py +0 -29
- flock/webapp/app/chat.py +0 -662
- flock/webapp/app/config.py +0 -104
- flock/webapp/app/dependencies.py +0 -117
- flock/webapp/app/main.py +0 -1086
- flock/webapp/app/middleware.py +0 -113
- flock/webapp/app/models_ui.py +0 -7
- flock/webapp/app/services/__init__.py +0 -0
- flock/webapp/app/services/feedback_file_service.py +0 -363
- flock/webapp/app/services/flock_service.py +0 -345
- flock/webapp/app/services/sharing_models.py +0 -81
- flock/webapp/app/services/sharing_store.py +0 -597
- flock/webapp/app/templates/theme_mapper.html +0 -326
- flock/webapp/app/theme_mapper.py +0 -811
- flock/webapp/app/utils.py +0 -85
- flock/webapp/run.py +0 -219
- flock/webapp/static/css/chat.css +0 -301
- flock/webapp/static/css/components.css +0 -167
- flock/webapp/static/css/header.css +0 -39
- flock/webapp/static/css/layout.css +0 -281
- flock/webapp/static/css/sidebar.css +0 -127
- flock/webapp/static/css/two-pane.css +0 -48
- flock/webapp/templates/base.html +0 -389
- flock/webapp/templates/chat.html +0 -152
- flock/webapp/templates/chat_settings.html +0 -19
- flock/webapp/templates/flock_editor.html +0 -16
- flock/webapp/templates/index.html +0 -12
- flock/webapp/templates/partials/_agent_detail_form.html +0 -93
- flock/webapp/templates/partials/_agent_list.html +0 -18
- flock/webapp/templates/partials/_agent_manager_view.html +0 -51
- flock/webapp/templates/partials/_agent_tools_checklist.html +0 -14
- flock/webapp/templates/partials/_chat_container.html +0 -15
- flock/webapp/templates/partials/_chat_messages.html +0 -57
- flock/webapp/templates/partials/_chat_settings_form.html +0 -85
- flock/webapp/templates/partials/_create_flock_form.html +0 -50
- flock/webapp/templates/partials/_dashboard_flock_detail.html +0 -17
- flock/webapp/templates/partials/_dashboard_flock_file_list.html +0 -16
- flock/webapp/templates/partials/_dashboard_flock_properties_preview.html +0 -28
- flock/webapp/templates/partials/_dashboard_upload_flock_form.html +0 -16
- flock/webapp/templates/partials/_dynamic_input_form_content.html +0 -22
- flock/webapp/templates/partials/_env_vars_table.html +0 -23
- flock/webapp/templates/partials/_execution_form.html +0 -127
- flock/webapp/templates/partials/_execution_view_container.html +0 -28
- flock/webapp/templates/partials/_flock_file_list.html +0 -23
- flock/webapp/templates/partials/_flock_properties_form.html +0 -52
- flock/webapp/templates/partials/_flock_upload_form.html +0 -16
- flock/webapp/templates/partials/_header_flock_status.html +0 -5
- flock/webapp/templates/partials/_live_logs.html +0 -13
- flock/webapp/templates/partials/_load_manager_view.html +0 -49
- flock/webapp/templates/partials/_registry_table.html +0 -25
- flock/webapp/templates/partials/_registry_viewer_content.html +0 -70
- flock/webapp/templates/partials/_results_display.html +0 -78
- flock/webapp/templates/partials/_settings_env_content.html +0 -9
- flock/webapp/templates/partials/_settings_theme_content.html +0 -14
- flock/webapp/templates/partials/_settings_view.html +0 -36
- flock/webapp/templates/partials/_share_chat_link_snippet.html +0 -11
- flock/webapp/templates/partials/_share_link_snippet.html +0 -35
- flock/webapp/templates/partials/_sidebar.html +0 -74
- flock/webapp/templates/partials/_structured_data_view.html +0 -40
- flock/webapp/templates/partials/_theme_preview.html +0 -36
- flock/webapp/templates/registry_viewer.html +0 -84
- flock/webapp/templates/shared_run_page.html +0 -140
- flock/workflow/__init__.py +0 -0
- flock/workflow/activities.py +0 -237
- flock/workflow/agent_activities.py +0 -24
- flock/workflow/agent_execution_activity.py +0 -240
- flock/workflow/flock_workflow.py +0 -225
- flock/workflow/temporal_config.py +0 -96
- flock/workflow/temporal_setup.py +0 -60
- flock_core-0.4.542.dist-info/METADATA +0 -676
- flock_core-0.4.542.dist-info/RECORD +0 -572
- flock_core-0.4.542.dist-info/entry_points.txt +0 -2
- /flock/{core/logging → logging}/formatters/themes.py +0 -0
- /flock/{core/logging → logging}/span_middleware/baggage_span_processor.py +0 -0
- /flock/{core/mcp → mcp}/util/__init__.py +0 -0
- {flock_core-0.4.542.dist-info → flock_core-0.5.0.dist-info}/WHEEL +0 -0
|
@@ -0,0 +1,357 @@
|
|
|
1
|
+
import dagre from 'dagre';
|
|
2
|
+
import { Node, Edge } from '@xyflow/react';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Phase 4: Graph Visualization & Dual Views - Layout Service
|
|
6
|
+
*
|
|
7
|
+
* Provides Dagre-based hierarchical layout algorithm for automatic node positioning.
|
|
8
|
+
* Supports both vertical (TB) and horizontal (LR) layouts with configurable spacing.
|
|
9
|
+
*
|
|
10
|
+
* REQUIREMENT: Must complete <200ms for 10 nodes
|
|
11
|
+
* SPECIFICATION: docs/specs/003-real-time-dashboard/PLAN.md Phase 4
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
export interface LayoutOptions {
|
|
15
|
+
direction?: 'TB' | 'LR' | 'BT' | 'RL';
|
|
16
|
+
nodeSpacing?: number;
|
|
17
|
+
rankSpacing?: number;
|
|
18
|
+
center?: { x: number; y: number }; // Optional center point for layout
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export interface LayoutResult {
|
|
22
|
+
nodes: Node[];
|
|
23
|
+
edges: Edge[];
|
|
24
|
+
width: number;
|
|
25
|
+
height: number;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
// Default node dimensions
|
|
29
|
+
const DEFAULT_NODE_WIDTH = 200;
|
|
30
|
+
const DEFAULT_NODE_HEIGHT = 80;
|
|
31
|
+
const MESSAGE_NODE_WIDTH = 150;
|
|
32
|
+
const MESSAGE_NODE_HEIGHT = 60;
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Get node dimensions based on node type
|
|
36
|
+
*/
|
|
37
|
+
function getNodeDimensions(node: Node): { width: number; height: number } {
|
|
38
|
+
if (node.type === 'message') {
|
|
39
|
+
return { width: MESSAGE_NODE_WIDTH, height: MESSAGE_NODE_HEIGHT };
|
|
40
|
+
}
|
|
41
|
+
return { width: DEFAULT_NODE_WIDTH, height: DEFAULT_NODE_HEIGHT };
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Apply hierarchical layout using Dagre algorithm
|
|
46
|
+
*
|
|
47
|
+
* @param nodes - Array of nodes to layout
|
|
48
|
+
* @param edges - Array of edges defining connections
|
|
49
|
+
* @param options - Layout configuration options
|
|
50
|
+
* @returns Layout result with positioned nodes and graph dimensions
|
|
51
|
+
*/
|
|
52
|
+
export function applyHierarchicalLayout(
|
|
53
|
+
nodes: Node[],
|
|
54
|
+
edges: Edge[],
|
|
55
|
+
options: LayoutOptions = {}
|
|
56
|
+
): LayoutResult {
|
|
57
|
+
const {
|
|
58
|
+
direction = 'TB',
|
|
59
|
+
center,
|
|
60
|
+
} = options;
|
|
61
|
+
|
|
62
|
+
// Handle empty graph
|
|
63
|
+
if (nodes.length === 0) {
|
|
64
|
+
return { nodes: [], edges, width: 0, height: 0 };
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
// Calculate dynamic spacing based on actual node sizes
|
|
68
|
+
// This ensures 200px minimum clearance regardless of node dimensions
|
|
69
|
+
let maxWidth = 0;
|
|
70
|
+
let maxHeight = 0;
|
|
71
|
+
|
|
72
|
+
nodes.forEach((node) => {
|
|
73
|
+
const { width, height } = getNodeDimensions(node);
|
|
74
|
+
maxWidth = Math.max(maxWidth, width);
|
|
75
|
+
maxHeight = Math.max(maxHeight, height);
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
// Spacing = half of max node size + 200px minimum clearance
|
|
79
|
+
const nodeSpacing = options.nodeSpacing ?? (maxWidth / 2 + 200);
|
|
80
|
+
const rankSpacing = options.rankSpacing ?? (maxHeight / 2 + 200);
|
|
81
|
+
|
|
82
|
+
// Create a new directed graph
|
|
83
|
+
const graph = new dagre.graphlib.Graph();
|
|
84
|
+
|
|
85
|
+
// Set graph layout options
|
|
86
|
+
graph.setGraph({
|
|
87
|
+
rankdir: direction,
|
|
88
|
+
nodesep: nodeSpacing,
|
|
89
|
+
ranksep: rankSpacing,
|
|
90
|
+
marginx: 20,
|
|
91
|
+
marginy: 20,
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
// Default edge configuration
|
|
95
|
+
graph.setDefaultEdgeLabel(() => ({}));
|
|
96
|
+
|
|
97
|
+
// Add nodes to the graph with their dimensions
|
|
98
|
+
nodes.forEach((node) => {
|
|
99
|
+
const { width, height } = getNodeDimensions(node);
|
|
100
|
+
graph.setNode(node.id, { width, height });
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
// Add edges to the graph
|
|
104
|
+
edges.forEach((edge) => {
|
|
105
|
+
graph.setEdge(edge.source, edge.target);
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
// Run the layout algorithm
|
|
109
|
+
dagre.layout(graph);
|
|
110
|
+
|
|
111
|
+
// Get graph dimensions first to calculate offset
|
|
112
|
+
const graphConfig = graph.graph();
|
|
113
|
+
const graphWidth = (graphConfig.width || 0) + 40; // Add margin
|
|
114
|
+
const graphHeight = (graphConfig.height || 0) + 40; // Add margin
|
|
115
|
+
|
|
116
|
+
// Calculate offset to center the layout around viewport center (or 0,0 if no center provided)
|
|
117
|
+
const offsetX = center ? center.x - graphWidth / 2 : 0;
|
|
118
|
+
const offsetY = center ? center.y - graphHeight / 2 : 0;
|
|
119
|
+
|
|
120
|
+
// Extract positioned nodes
|
|
121
|
+
const layoutedNodes = nodes.map((node) => {
|
|
122
|
+
const nodeWithPosition = graph.node(node.id);
|
|
123
|
+
|
|
124
|
+
// Dagre positions nodes at their center, we need top-left corner
|
|
125
|
+
const { width, height } = getNodeDimensions(node);
|
|
126
|
+
|
|
127
|
+
return {
|
|
128
|
+
...node,
|
|
129
|
+
position: {
|
|
130
|
+
x: nodeWithPosition.x - width / 2 + offsetX,
|
|
131
|
+
y: nodeWithPosition.y - height / 2 + offsetY,
|
|
132
|
+
},
|
|
133
|
+
};
|
|
134
|
+
});
|
|
135
|
+
|
|
136
|
+
return {
|
|
137
|
+
nodes: layoutedNodes,
|
|
138
|
+
edges,
|
|
139
|
+
width: graphWidth,
|
|
140
|
+
height: graphHeight,
|
|
141
|
+
};
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
/**
|
|
145
|
+
* Apply circular layout - nodes arranged in a circle
|
|
146
|
+
*/
|
|
147
|
+
export function applyCircularLayout(
|
|
148
|
+
nodes: Node[],
|
|
149
|
+
edges: Edge[],
|
|
150
|
+
options: LayoutOptions = {}
|
|
151
|
+
): LayoutResult {
|
|
152
|
+
const { center } = options;
|
|
153
|
+
|
|
154
|
+
if (nodes.length === 0) {
|
|
155
|
+
return { nodes: [], edges, width: 0, height: 0 };
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
// Calculate radius based on number of nodes and their sizes
|
|
159
|
+
let maxWidth = 0;
|
|
160
|
+
let maxHeight = 0;
|
|
161
|
+
nodes.forEach((node) => {
|
|
162
|
+
const { width, height } = getNodeDimensions(node);
|
|
163
|
+
maxWidth = Math.max(maxWidth, width);
|
|
164
|
+
maxHeight = Math.max(maxHeight, height);
|
|
165
|
+
});
|
|
166
|
+
|
|
167
|
+
const minSpacing = 200; // 200px minimum clearance
|
|
168
|
+
const nodeSize = Math.max(maxWidth, maxHeight);
|
|
169
|
+
const circumference = nodes.length * (nodeSize + minSpacing);
|
|
170
|
+
const radius = circumference / (2 * Math.PI);
|
|
171
|
+
|
|
172
|
+
const centerX = center?.x ?? 0;
|
|
173
|
+
const centerY = center?.y ?? 0;
|
|
174
|
+
|
|
175
|
+
const layoutedNodes = nodes.map((node, index) => {
|
|
176
|
+
const angle = (2 * Math.PI * index) / nodes.length;
|
|
177
|
+
const { width, height } = getNodeDimensions(node);
|
|
178
|
+
|
|
179
|
+
return {
|
|
180
|
+
...node,
|
|
181
|
+
position: {
|
|
182
|
+
x: centerX + radius * Math.cos(angle) - width / 2,
|
|
183
|
+
y: centerY + radius * Math.sin(angle) - height / 2,
|
|
184
|
+
},
|
|
185
|
+
};
|
|
186
|
+
});
|
|
187
|
+
|
|
188
|
+
const graphWidth = radius * 2 + maxWidth;
|
|
189
|
+
const graphHeight = radius * 2 + maxHeight;
|
|
190
|
+
|
|
191
|
+
return {
|
|
192
|
+
nodes: layoutedNodes,
|
|
193
|
+
edges,
|
|
194
|
+
width: graphWidth,
|
|
195
|
+
height: graphHeight,
|
|
196
|
+
};
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
/**
|
|
200
|
+
* Apply grid layout - nodes arranged in a grid
|
|
201
|
+
*/
|
|
202
|
+
export function applyGridLayout(
|
|
203
|
+
nodes: Node[],
|
|
204
|
+
edges: Edge[],
|
|
205
|
+
options: LayoutOptions = {}
|
|
206
|
+
): LayoutResult {
|
|
207
|
+
const { center } = options;
|
|
208
|
+
|
|
209
|
+
if (nodes.length === 0) {
|
|
210
|
+
return { nodes: [], edges, width: 0, height: 0 };
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
// Calculate grid dimensions
|
|
214
|
+
const cols = Math.ceil(Math.sqrt(nodes.length));
|
|
215
|
+
const rows = Math.ceil(nodes.length / cols);
|
|
216
|
+
|
|
217
|
+
let maxWidth = 0;
|
|
218
|
+
let maxHeight = 0;
|
|
219
|
+
nodes.forEach((node) => {
|
|
220
|
+
const { width, height } = getNodeDimensions(node);
|
|
221
|
+
maxWidth = Math.max(maxWidth, width);
|
|
222
|
+
maxHeight = Math.max(maxHeight, height);
|
|
223
|
+
});
|
|
224
|
+
|
|
225
|
+
const minSpacing = 200;
|
|
226
|
+
const cellWidth = maxWidth + minSpacing;
|
|
227
|
+
const cellHeight = maxHeight + minSpacing;
|
|
228
|
+
|
|
229
|
+
const graphWidth = cols * cellWidth;
|
|
230
|
+
const graphHeight = rows * cellHeight;
|
|
231
|
+
|
|
232
|
+
const startX = center ? center.x - graphWidth / 2 : 0;
|
|
233
|
+
const startY = center ? center.y - graphHeight / 2 : 0;
|
|
234
|
+
|
|
235
|
+
const layoutedNodes = nodes.map((node, index) => {
|
|
236
|
+
const col = index % cols;
|
|
237
|
+
const row = Math.floor(index / cols);
|
|
238
|
+
const { width, height } = getNodeDimensions(node);
|
|
239
|
+
|
|
240
|
+
return {
|
|
241
|
+
...node,
|
|
242
|
+
position: {
|
|
243
|
+
x: startX + col * cellWidth + (cellWidth - width) / 2,
|
|
244
|
+
y: startY + row * cellHeight + (cellHeight - height) / 2,
|
|
245
|
+
},
|
|
246
|
+
};
|
|
247
|
+
});
|
|
248
|
+
|
|
249
|
+
return {
|
|
250
|
+
nodes: layoutedNodes,
|
|
251
|
+
edges,
|
|
252
|
+
width: graphWidth,
|
|
253
|
+
height: graphHeight,
|
|
254
|
+
};
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
/**
|
|
258
|
+
* Apply random layout - nodes placed randomly with minimum spacing
|
|
259
|
+
*/
|
|
260
|
+
export function applyRandomLayout(
|
|
261
|
+
nodes: Node[],
|
|
262
|
+
edges: Edge[],
|
|
263
|
+
options: LayoutOptions = {}
|
|
264
|
+
): LayoutResult {
|
|
265
|
+
const { center } = options;
|
|
266
|
+
|
|
267
|
+
if (nodes.length === 0) {
|
|
268
|
+
return { nodes: [], edges, width: 0, height: 0 };
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
let maxWidth = 0;
|
|
272
|
+
let maxHeight = 0;
|
|
273
|
+
nodes.forEach((node) => {
|
|
274
|
+
const { width, height } = getNodeDimensions(node);
|
|
275
|
+
maxWidth = Math.max(maxWidth, width);
|
|
276
|
+
maxHeight = Math.max(maxHeight, height);
|
|
277
|
+
});
|
|
278
|
+
|
|
279
|
+
const minSpacing = 200;
|
|
280
|
+
const spreadFactor = 1.5; // How much to spread nodes apart
|
|
281
|
+
const areaSize = Math.sqrt(nodes.length) * (maxWidth + maxHeight + minSpacing) * spreadFactor;
|
|
282
|
+
|
|
283
|
+
const centerX = center?.x ?? 0;
|
|
284
|
+
const centerY = center?.y ?? 0;
|
|
285
|
+
|
|
286
|
+
// Place nodes randomly, checking for collisions
|
|
287
|
+
const layoutedNodes: Node[] = [];
|
|
288
|
+
const maxAttempts = 100;
|
|
289
|
+
|
|
290
|
+
nodes.forEach((node) => {
|
|
291
|
+
const { width, height } = getNodeDimensions(node);
|
|
292
|
+
let placed = false;
|
|
293
|
+
let attempts = 0;
|
|
294
|
+
|
|
295
|
+
while (!placed && attempts < maxAttempts) {
|
|
296
|
+
const x = centerX + (Math.random() - 0.5) * areaSize - width / 2;
|
|
297
|
+
const y = centerY + (Math.random() - 0.5) * areaSize - height / 2;
|
|
298
|
+
|
|
299
|
+
// Check if this position collides with existing nodes
|
|
300
|
+
const collides = layoutedNodes.some((existingNode) => {
|
|
301
|
+
const exDims = getNodeDimensions(existingNode);
|
|
302
|
+
const dx = Math.abs(x - existingNode.position.x);
|
|
303
|
+
const dy = Math.abs(y - existingNode.position.y);
|
|
304
|
+
return dx < (width + exDims.width) / 2 + minSpacing &&
|
|
305
|
+
dy < (height + exDims.height) / 2 + minSpacing;
|
|
306
|
+
});
|
|
307
|
+
|
|
308
|
+
if (!collides) {
|
|
309
|
+
layoutedNodes.push({
|
|
310
|
+
...node,
|
|
311
|
+
position: { x, y },
|
|
312
|
+
});
|
|
313
|
+
placed = true;
|
|
314
|
+
}
|
|
315
|
+
attempts++;
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
// If we couldn't place it without collision, just place it anyway
|
|
319
|
+
if (!placed) {
|
|
320
|
+
layoutedNodes.push({
|
|
321
|
+
...node,
|
|
322
|
+
position: {
|
|
323
|
+
x: centerX + (Math.random() - 0.5) * areaSize - width / 2,
|
|
324
|
+
y: centerY + (Math.random() - 0.5) * areaSize - height / 2,
|
|
325
|
+
},
|
|
326
|
+
});
|
|
327
|
+
}
|
|
328
|
+
});
|
|
329
|
+
|
|
330
|
+
return {
|
|
331
|
+
nodes: layoutedNodes,
|
|
332
|
+
edges,
|
|
333
|
+
width: areaSize,
|
|
334
|
+
height: areaSize,
|
|
335
|
+
};
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
/**
|
|
339
|
+
* Legacy function name for backwards compatibility
|
|
340
|
+
* Delegates to applyHierarchicalLayout
|
|
341
|
+
*/
|
|
342
|
+
export function applyDagreLayout(
|
|
343
|
+
nodes: Node[],
|
|
344
|
+
edges: Edge[],
|
|
345
|
+
direction: 'TB' | 'LR' = 'TB',
|
|
346
|
+
nodeSpacing?: number,
|
|
347
|
+
rankSpacing?: number,
|
|
348
|
+
center?: { x: number; y: number }
|
|
349
|
+
): Node[] {
|
|
350
|
+
const result = applyHierarchicalLayout(nodes, edges, {
|
|
351
|
+
direction,
|
|
352
|
+
nodeSpacing,
|
|
353
|
+
rankSpacing,
|
|
354
|
+
center
|
|
355
|
+
});
|
|
356
|
+
return result.nodes;
|
|
357
|
+
}
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Theme Applicator
|
|
3
|
+
*
|
|
4
|
+
* Applies terminal themes to dashboard UI by mapping 8-color palette
|
|
5
|
+
* to CSS custom properties.
|
|
6
|
+
*
|
|
7
|
+
* See: docs/specs/004-ui-improvements/THEME_MAPPING.md
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import { TerminalTheme } from '../types/theme';
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Convert hex color to rgba with alpha channel
|
|
14
|
+
*/
|
|
15
|
+
function hexToRgba(hex: string, alpha: number): string {
|
|
16
|
+
const r = parseInt(hex.slice(1, 3), 16);
|
|
17
|
+
const g = parseInt(hex.slice(3, 5), 16);
|
|
18
|
+
const b = parseInt(hex.slice(5, 7), 16);
|
|
19
|
+
return `rgba(${r}, ${g}, ${b}, ${alpha})`;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Apply a theme to the dashboard by updating CSS variables
|
|
24
|
+
*/
|
|
25
|
+
export function applyTheme(theme: TerminalTheme): void {
|
|
26
|
+
const root = document.documentElement;
|
|
27
|
+
const { colors } = theme;
|
|
28
|
+
|
|
29
|
+
// Background Layers
|
|
30
|
+
root.style.setProperty('--color-bg-base', colors.primary.background);
|
|
31
|
+
root.style.setProperty('--color-bg-elevated', colors.selection.background);
|
|
32
|
+
root.style.setProperty('--color-bg-surface', colors.normal.black);
|
|
33
|
+
root.style.setProperty('--color-bg-overlay', colors.bright.black);
|
|
34
|
+
root.style.setProperty('--color-bg-float', hexToRgba(colors.normal.white, 0.1));
|
|
35
|
+
|
|
36
|
+
// Text Colors
|
|
37
|
+
root.style.setProperty('--color-text-primary', colors.primary.foreground);
|
|
38
|
+
root.style.setProperty('--color-text-secondary', colors.bright.white);
|
|
39
|
+
root.style.setProperty('--color-text-tertiary', colors.selection.text);
|
|
40
|
+
root.style.setProperty('--color-text-muted', colors.cursor.text);
|
|
41
|
+
root.style.setProperty('--color-text-on-primary', colors.selection.text);
|
|
42
|
+
|
|
43
|
+
// Brand & Accent Colors
|
|
44
|
+
root.style.setProperty('--color-primary-500', colors.normal.blue);
|
|
45
|
+
root.style.setProperty('--color-primary-400', colors.bright.blue);
|
|
46
|
+
root.style.setProperty('--color-primary-600', colors.normal.blue); // Slightly darker for hover
|
|
47
|
+
root.style.setProperty('--color-secondary-500', colors.normal.magenta);
|
|
48
|
+
root.style.setProperty('--color-secondary-400', colors.bright.magenta);
|
|
49
|
+
root.style.setProperty('--color-tertiary-500', colors.normal.cyan);
|
|
50
|
+
|
|
51
|
+
// Semantic Status Colors
|
|
52
|
+
root.style.setProperty('--color-success', colors.normal.green);
|
|
53
|
+
root.style.setProperty('--color-success-light', colors.bright.green);
|
|
54
|
+
root.style.setProperty('--color-error', colors.normal.red);
|
|
55
|
+
root.style.setProperty('--color-error-light', colors.bright.red);
|
|
56
|
+
root.style.setProperty('--color-warning', colors.normal.yellow);
|
|
57
|
+
root.style.setProperty('--color-warning-light', colors.bright.yellow);
|
|
58
|
+
root.style.setProperty('--color-info', colors.normal.cyan);
|
|
59
|
+
root.style.setProperty('--color-info-light', colors.bright.cyan);
|
|
60
|
+
|
|
61
|
+
// Graph-Specific Colors (can be overridden by user settings)
|
|
62
|
+
// Only set if user hasn't customized them
|
|
63
|
+
const currentIdleColor = root.style.getPropertyValue('--agent-idle-color');
|
|
64
|
+
if (!currentIdleColor || currentIdleColor === '#60a5fa') {
|
|
65
|
+
root.style.setProperty('--agent-idle-color', colors.normal.cyan);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
const currentActiveColor = root.style.getPropertyValue('--agent-active-color');
|
|
69
|
+
if (!currentActiveColor || currentActiveColor === '#10b981') {
|
|
70
|
+
root.style.setProperty('--agent-active-color', colors.normal.green);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
const currentErrorColor = root.style.getPropertyValue('--agent-error-color');
|
|
74
|
+
if (!currentErrorColor || currentErrorColor === '#ef4444') {
|
|
75
|
+
root.style.setProperty('--agent-error-color', colors.normal.red);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
// Border & Divider Colors
|
|
79
|
+
root.style.setProperty('--color-border-default', colors.bright.black);
|
|
80
|
+
root.style.setProperty('--color-border-subtle', hexToRgba(colors.normal.white, 0.2));
|
|
81
|
+
root.style.setProperty('--color-border-strong', colors.cursor.cursor);
|
|
82
|
+
root.style.setProperty('--color-border-focus', colors.normal.blue);
|
|
83
|
+
root.style.setProperty('--color-border-error', colors.normal.red);
|
|
84
|
+
|
|
85
|
+
// Special Effect Colors
|
|
86
|
+
root.style.setProperty('--color-glass-bg', hexToRgba(colors.selection.background, 0.8));
|
|
87
|
+
root.style.setProperty('--color-glow-primary', colors.cursor.cursor);
|
|
88
|
+
root.style.setProperty('--shadow-glow-primary', `0 0 0 3px ${hexToRgba(colors.bright.blue, 0.5)}`);
|
|
89
|
+
root.style.setProperty('--shadow-glow-error', `0 0 0 3px ${hexToRgba(colors.bright.red, 0.5)}`);
|
|
90
|
+
|
|
91
|
+
// Edge colors
|
|
92
|
+
root.style.setProperty('--color-edge-default', colors.bright.black);
|
|
93
|
+
root.style.setProperty('--color-edge-message', colors.bright.yellow);
|
|
94
|
+
root.style.setProperty('--color-edge-active', colors.bright.blue);
|
|
95
|
+
|
|
96
|
+
// Node colors
|
|
97
|
+
root.style.setProperty('--color-node-message-border', colors.normal.magenta);
|
|
98
|
+
|
|
99
|
+
console.log(`[Theme] Applied theme: ${theme.name}`);
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* Reset to default theme (current design system colors)
|
|
104
|
+
*/
|
|
105
|
+
export function resetToDefaultTheme(): void {
|
|
106
|
+
const root = document.documentElement;
|
|
107
|
+
|
|
108
|
+
// Reset to original design system values
|
|
109
|
+
root.style.setProperty('--color-bg-base', '#0a0a0b');
|
|
110
|
+
root.style.setProperty('--color-bg-elevated', '#121214');
|
|
111
|
+
root.style.setProperty('--color-bg-surface', '#1a1a1e');
|
|
112
|
+
root.style.setProperty('--color-bg-overlay', '#232329');
|
|
113
|
+
root.style.setProperty('--color-bg-float', '#2a2a32');
|
|
114
|
+
|
|
115
|
+
root.style.setProperty('--color-text-primary', '#e5e7eb');
|
|
116
|
+
root.style.setProperty('--color-text-secondary', '#9ca3af');
|
|
117
|
+
root.style.setProperty('--color-text-tertiary', '#6b7280');
|
|
118
|
+
|
|
119
|
+
root.style.setProperty('--color-primary-500', '#6366f1');
|
|
120
|
+
root.style.setProperty('--color-primary-400', '#818cf8');
|
|
121
|
+
root.style.setProperty('--color-primary-600', '#4f46e5');
|
|
122
|
+
|
|
123
|
+
console.log('[Theme] Reset to default theme');
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
* Get a preview swatch array for a theme (8 colors)
|
|
128
|
+
*/
|
|
129
|
+
export function getThemePreview(theme: TerminalTheme): string[] {
|
|
130
|
+
return [
|
|
131
|
+
theme.colors.normal.black,
|
|
132
|
+
theme.colors.normal.red,
|
|
133
|
+
theme.colors.normal.green,
|
|
134
|
+
theme.colors.normal.yellow,
|
|
135
|
+
theme.colors.normal.blue,
|
|
136
|
+
theme.colors.normal.magenta,
|
|
137
|
+
theme.colors.normal.cyan,
|
|
138
|
+
theme.colors.normal.white,
|
|
139
|
+
];
|
|
140
|
+
}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Theme Service
|
|
3
|
+
*
|
|
4
|
+
* Fetches terminal themes from the backend API.
|
|
5
|
+
* Themes are loaded from TOML files in src/flock/themes/
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import { TerminalTheme, ThemeListResponse, ThemeDataResponse } from '../types/theme';
|
|
9
|
+
|
|
10
|
+
const BASE_URL = import.meta.env.VITE_API_BASE_URL || '/api';
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Fetch list of available theme names
|
|
14
|
+
*/
|
|
15
|
+
export async function fetchThemeList(): Promise<string[]> {
|
|
16
|
+
try {
|
|
17
|
+
const response = await fetch(`${BASE_URL}/themes`, {
|
|
18
|
+
method: 'GET',
|
|
19
|
+
headers: {
|
|
20
|
+
'Content-Type': 'application/json',
|
|
21
|
+
},
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
if (!response.ok) {
|
|
25
|
+
throw new Error(`Failed to fetch themes: ${response.statusText}`);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
const data: ThemeListResponse = await response.json();
|
|
29
|
+
return data.themes;
|
|
30
|
+
} catch (error) {
|
|
31
|
+
console.error('Error fetching theme list:', error);
|
|
32
|
+
throw error;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Fetch a specific theme by name
|
|
38
|
+
*/
|
|
39
|
+
export async function fetchTheme(themeName: string): Promise<TerminalTheme> {
|
|
40
|
+
try {
|
|
41
|
+
const response = await fetch(`${BASE_URL}/themes/${themeName}`, {
|
|
42
|
+
method: 'GET',
|
|
43
|
+
headers: {
|
|
44
|
+
'Content-Type': 'application/json',
|
|
45
|
+
},
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
if (!response.ok) {
|
|
49
|
+
throw new Error(`Failed to fetch theme "${themeName}": ${response.statusText}`);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
const data: ThemeDataResponse = await response.json();
|
|
53
|
+
return {
|
|
54
|
+
name: data.name,
|
|
55
|
+
colors: data.data.colors,
|
|
56
|
+
};
|
|
57
|
+
} catch (error) {
|
|
58
|
+
console.error(`Error fetching theme "${themeName}":`, error);
|
|
59
|
+
throw error;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Get popular/recommended themes
|
|
65
|
+
*/
|
|
66
|
+
export const POPULAR_THEMES = [
|
|
67
|
+
'dracula',
|
|
68
|
+
'nord',
|
|
69
|
+
'catppuccin-mocha',
|
|
70
|
+
'tokyonight',
|
|
71
|
+
'gruvboxdark',
|
|
72
|
+
'solarized-dark',
|
|
73
|
+
'github-dark',
|
|
74
|
+
'one-half-dark',
|
|
75
|
+
'monokai',
|
|
76
|
+
'material',
|
|
77
|
+
];
|