flock-core 0.4.543__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.543.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.543.dist-info/METADATA +0 -676
- flock_core-0.4.543.dist-info/RECORD +0 -572
- flock_core-0.4.543.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.543.dist-info → flock_core-0.5.0.dist-info}/WHEEL +0 -0
flock/tools/web_tools.py
DELETED
|
@@ -1,92 +0,0 @@
|
|
|
1
|
-
|
|
2
|
-
import importlib
|
|
3
|
-
import os
|
|
4
|
-
from typing import Literal
|
|
5
|
-
|
|
6
|
-
from flock.core.logging.trace_and_logged import traced_and_logged
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
@traced_and_logged
|
|
10
|
-
def web_search_tavily(query: str):
|
|
11
|
-
if importlib.util.find_spec("tavily") is not None:
|
|
12
|
-
from tavily import TavilyClient
|
|
13
|
-
|
|
14
|
-
client = TavilyClient(api_key=os.getenv("TAVILY_API_KEY"))
|
|
15
|
-
try:
|
|
16
|
-
response = client.search(query, include_answer=True) # type: ignore
|
|
17
|
-
return response
|
|
18
|
-
except Exception:
|
|
19
|
-
raise
|
|
20
|
-
else:
|
|
21
|
-
raise ImportError(
|
|
22
|
-
"Optional tool dependencies not installed. Install with 'pip install flock-mcp[all]'."
|
|
23
|
-
)
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
@traced_and_logged
|
|
27
|
-
def web_search_duckduckgo(
|
|
28
|
-
keywords: str, search_type: Literal["news", "web"] = "web"
|
|
29
|
-
):
|
|
30
|
-
try:
|
|
31
|
-
if importlib.util.find_spec("ddgs") is not None:
|
|
32
|
-
from ddgs import DDGS
|
|
33
|
-
|
|
34
|
-
if search_type == "news":
|
|
35
|
-
response = DDGS().news(keywords)
|
|
36
|
-
else:
|
|
37
|
-
response = DDGS().text(keywords)
|
|
38
|
-
|
|
39
|
-
return response
|
|
40
|
-
else:
|
|
41
|
-
raise ImportError(
|
|
42
|
-
"Optional tool dependencies not installed. Install with 'pip install flock-mcp[all]'."
|
|
43
|
-
)
|
|
44
|
-
except Exception:
|
|
45
|
-
raise
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
@traced_and_logged
|
|
49
|
-
def web_search_bing(keywords: str):
|
|
50
|
-
try:
|
|
51
|
-
import httpx
|
|
52
|
-
|
|
53
|
-
subscription_key = os.environ["BING_SEARCH_V7_SUBSCRIPTION_KEY"]
|
|
54
|
-
endpoint = "https://api.bing.microsoft.com/v7.0/search"
|
|
55
|
-
|
|
56
|
-
# Query term(s) to search for.
|
|
57
|
-
query = keywords
|
|
58
|
-
|
|
59
|
-
# Construct a request
|
|
60
|
-
mkt = "en-US"
|
|
61
|
-
params = {"q": query, "mkt": mkt}
|
|
62
|
-
headers = {"Ocp-Apim-Subscription-Key": subscription_key}
|
|
63
|
-
|
|
64
|
-
response = httpx.get(endpoint, headers=headers, params=params)
|
|
65
|
-
response.raise_for_status()
|
|
66
|
-
search_results = response.json()
|
|
67
|
-
return search_results["webPages"]
|
|
68
|
-
except Exception:
|
|
69
|
-
raise
|
|
70
|
-
|
|
71
|
-
@traced_and_logged
|
|
72
|
-
def web_content_as_markdown(url: str) -> str:
|
|
73
|
-
if (
|
|
74
|
-
importlib.util.find_spec("httpx") is not None
|
|
75
|
-
and importlib.util.find_spec("markdownify") is not None
|
|
76
|
-
):
|
|
77
|
-
import httpx
|
|
78
|
-
from markdownify import markdownify as md
|
|
79
|
-
|
|
80
|
-
try:
|
|
81
|
-
response = httpx.get(url)
|
|
82
|
-
response.raise_for_status()
|
|
83
|
-
markdown = md(response.text)
|
|
84
|
-
return markdown
|
|
85
|
-
except Exception:
|
|
86
|
-
raise
|
|
87
|
-
else:
|
|
88
|
-
raise ImportError(
|
|
89
|
-
"Optional tool dependencies not installed. Install with 'pip install flock-mcp[all]'."
|
|
90
|
-
)
|
|
91
|
-
|
|
92
|
-
|
flock/tools/zendesk_tools.py
DELETED
|
@@ -1,501 +0,0 @@
|
|
|
1
|
-
"""Tools for interacting with Zendesk."""
|
|
2
|
-
|
|
3
|
-
import os
|
|
4
|
-
|
|
5
|
-
import httpx
|
|
6
|
-
from mcp.server.fastmcp import FastMCP
|
|
7
|
-
|
|
8
|
-
from flock.core.logging.logging import get_logger
|
|
9
|
-
|
|
10
|
-
mcp = FastMCP("ZendeskTools")
|
|
11
|
-
logger = get_logger(__name__)
|
|
12
|
-
|
|
13
|
-
def _get_headers() -> dict:
|
|
14
|
-
logger.debug("Preparing headers for Zendesk API request")
|
|
15
|
-
|
|
16
|
-
token = os.getenv("ZENDESK_BEARER_TOKEN")
|
|
17
|
-
if not token:
|
|
18
|
-
logger.error("ZENDESK_BEARER_TOKEN environment variable is not set")
|
|
19
|
-
raise ValueError(
|
|
20
|
-
"ZENDESK_BEARER_TOKEN environment variable is not set"
|
|
21
|
-
)
|
|
22
|
-
|
|
23
|
-
logger.debug("Successfully retrieved bearer token from environment")
|
|
24
|
-
# Log a masked version of the token for debugging
|
|
25
|
-
masked_token = f"{token[:10]}...{token[-4:] if len(token) > 14 else 'short'}"
|
|
26
|
-
logger.debug(f"Using bearer token: {masked_token}")
|
|
27
|
-
logger.debug("Headers prepared successfully")
|
|
28
|
-
|
|
29
|
-
return {
|
|
30
|
-
"Authorization": f"Bearer {token}",
|
|
31
|
-
"Accept": "application/json",
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
@mcp.tool()
|
|
36
|
-
def zendesk_get_tickets(number_of_tickets: int = 10) -> list[dict]:
|
|
37
|
-
"""Get all tickets."""
|
|
38
|
-
logger.info(f"Starting zendesk_get_tickets with number_of_tickets: {number_of_tickets}")
|
|
39
|
-
|
|
40
|
-
ZENDESK_SUBDOMAIN = os.getenv("ZENDESK_SUBDOMAIN_TICKET")
|
|
41
|
-
logger.debug(f"Using Zendesk subdomain: {ZENDESK_SUBDOMAIN}")
|
|
42
|
-
|
|
43
|
-
BASE_URL = f"https://{ZENDESK_SUBDOMAIN}.zendesk.com"
|
|
44
|
-
url = f"{BASE_URL}/api/v2/tickets.json"
|
|
45
|
-
logger.debug(f"Initial URL: {url}")
|
|
46
|
-
|
|
47
|
-
all_tickets = []
|
|
48
|
-
page_count = 0
|
|
49
|
-
|
|
50
|
-
with httpx.Client(headers=_get_headers(), timeout=30.0) as client:
|
|
51
|
-
logger.debug("Created HTTP client for Zendesk API")
|
|
52
|
-
|
|
53
|
-
while url and len(all_tickets) < number_of_tickets:
|
|
54
|
-
page_count += 1
|
|
55
|
-
logger.debug(f"Fetching page {page_count} from URL: {url}")
|
|
56
|
-
|
|
57
|
-
try:
|
|
58
|
-
response = client.get(url)
|
|
59
|
-
response.raise_for_status()
|
|
60
|
-
logger.debug(f"Successfully received response with status: {response.status_code}")
|
|
61
|
-
|
|
62
|
-
data = response.json()
|
|
63
|
-
tickets = data.get("tickets", [])
|
|
64
|
-
logger.debug(f"Retrieved {len(tickets)} tickets from page {page_count}")
|
|
65
|
-
|
|
66
|
-
all_tickets.extend(tickets)
|
|
67
|
-
logger.debug(f"Total tickets collected so far: {len(all_tickets)}")
|
|
68
|
-
|
|
69
|
-
url = data.get("next_page")
|
|
70
|
-
if url:
|
|
71
|
-
logger.debug(f"Next page URL: {url}")
|
|
72
|
-
else:
|
|
73
|
-
logger.debug("No more pages available")
|
|
74
|
-
|
|
75
|
-
except Exception as e:
|
|
76
|
-
logger.error(f"Error fetching tickets on page {page_count}: {e}")
|
|
77
|
-
raise
|
|
78
|
-
|
|
79
|
-
logger.info(f"Successfully retrieved {len(all_tickets)} tickets across {page_count} pages")
|
|
80
|
-
return all_tickets
|
|
81
|
-
|
|
82
|
-
@mcp.tool()
|
|
83
|
-
def zendesk_get_ticket_by_id(ticket_id: str) -> dict:
|
|
84
|
-
"""Get a ticket by ID."""
|
|
85
|
-
logger.info(f"Starting zendesk_get_ticket_by_id for ticket_id: {ticket_id}")
|
|
86
|
-
|
|
87
|
-
ZENDESK_SUBDOMAIN = os.getenv("ZENDESK_SUBDOMAIN_TICKET")
|
|
88
|
-
logger.debug(f"Using Zendesk subdomain: {ZENDESK_SUBDOMAIN}")
|
|
89
|
-
|
|
90
|
-
BASE_URL = f"https://{ZENDESK_SUBDOMAIN}.zendesk.com"
|
|
91
|
-
url = f"{BASE_URL}/api/v2/tickets/{ticket_id}"
|
|
92
|
-
logger.debug(f"Request URL: {url}")
|
|
93
|
-
|
|
94
|
-
with httpx.Client(headers=_get_headers(), timeout=30.0) as client:
|
|
95
|
-
logger.debug("Created HTTP client for Zendesk API")
|
|
96
|
-
|
|
97
|
-
try:
|
|
98
|
-
logger.debug(f"Making GET request for ticket {ticket_id}")
|
|
99
|
-
response = client.get(url)
|
|
100
|
-
response.raise_for_status()
|
|
101
|
-
logger.debug(f"Successfully received response with status: {response.status_code}")
|
|
102
|
-
|
|
103
|
-
ticket_data = response.json()["ticket"]
|
|
104
|
-
logger.info(f"Successfully retrieved ticket {ticket_id} with subject: {ticket_data.get('subject', 'N/A')}")
|
|
105
|
-
return ticket_data
|
|
106
|
-
|
|
107
|
-
except Exception as e:
|
|
108
|
-
logger.error(f"Error fetching ticket {ticket_id}: {e}")
|
|
109
|
-
raise
|
|
110
|
-
|
|
111
|
-
@mcp.tool()
|
|
112
|
-
def zendesk_get_comments_by_ticket_id(ticket_id: str) -> list[dict]:
|
|
113
|
-
"""Get all comments for a ticket."""
|
|
114
|
-
logger.info(f"Starting zendesk_get_comments_by_ticket_id for ticket_id: {ticket_id}")
|
|
115
|
-
|
|
116
|
-
ZENDESK_SUBDOMAIN = os.getenv("ZENDESK_SUBDOMAIN_TICKET")
|
|
117
|
-
logger.debug(f"Using Zendesk subdomain: {ZENDESK_SUBDOMAIN}")
|
|
118
|
-
|
|
119
|
-
BASE_URL = f"https://{ZENDESK_SUBDOMAIN}.zendesk.com"
|
|
120
|
-
url = f"{BASE_URL}/api/v2/tickets/{ticket_id}/comments"
|
|
121
|
-
logger.debug(f"Request URL: {url}")
|
|
122
|
-
|
|
123
|
-
with httpx.Client(headers=_get_headers(), timeout=30.0) as client:
|
|
124
|
-
logger.debug("Created HTTP client for Zendesk API")
|
|
125
|
-
|
|
126
|
-
try:
|
|
127
|
-
logger.debug(f"Making GET request for comments of ticket {ticket_id}")
|
|
128
|
-
response = client.get(url)
|
|
129
|
-
response.raise_for_status()
|
|
130
|
-
logger.debug(f"Successfully received response with status: {response.status_code}")
|
|
131
|
-
|
|
132
|
-
comments = response.json()["comments"]
|
|
133
|
-
logger.info(f"Successfully retrieved {len(comments)} comments for ticket {ticket_id}")
|
|
134
|
-
return comments
|
|
135
|
-
|
|
136
|
-
except Exception as e:
|
|
137
|
-
logger.error(f"Error fetching comments for ticket {ticket_id}: {e}")
|
|
138
|
-
raise
|
|
139
|
-
|
|
140
|
-
@mcp.tool()
|
|
141
|
-
def zendesk_get_article_by_id(article_id: str) -> dict:
|
|
142
|
-
"""Get an article by ID."""
|
|
143
|
-
logger.info(f"Starting zendesk_get_article_by_id for article_id: {article_id}")
|
|
144
|
-
|
|
145
|
-
ZENDESK_LOCALE = os.getenv("ZENDESK_ARTICLE_LOCALE")
|
|
146
|
-
ZENDESK_SUBDOMAIN = os.getenv("ZENDESK_SUBDOMAIN_ARTICLE")
|
|
147
|
-
logger.debug(f"Using locale: {ZENDESK_LOCALE}, subdomain: {ZENDESK_SUBDOMAIN}")
|
|
148
|
-
|
|
149
|
-
BASE_URL = f"https://{ZENDESK_SUBDOMAIN}.zendesk.com"
|
|
150
|
-
url = (
|
|
151
|
-
f"{BASE_URL}/api/v2/help_center/{ZENDESK_LOCALE}/articles/{article_id}"
|
|
152
|
-
)
|
|
153
|
-
logger.debug(f"Request URL: {url}")
|
|
154
|
-
|
|
155
|
-
with httpx.Client(headers=_get_headers(), timeout=30.0) as client:
|
|
156
|
-
logger.debug("Created HTTP client for Zendesk API")
|
|
157
|
-
|
|
158
|
-
try:
|
|
159
|
-
logger.debug(f"Making GET request for article {article_id}")
|
|
160
|
-
response = client.get(url)
|
|
161
|
-
response.raise_for_status()
|
|
162
|
-
logger.debug(f"Successfully received response with status: {response.status_code}")
|
|
163
|
-
|
|
164
|
-
article = response.json()["article"]
|
|
165
|
-
logger.info(f"Successfully retrieved article {article_id} with title: {article.get('title', 'N/A')}")
|
|
166
|
-
return article
|
|
167
|
-
|
|
168
|
-
except Exception as e:
|
|
169
|
-
logger.error(f"Error fetching article {article_id}: {e}")
|
|
170
|
-
raise
|
|
171
|
-
|
|
172
|
-
@mcp.tool()
|
|
173
|
-
def zendesk_get_articles() -> list[dict]:
|
|
174
|
-
"""Get all articles."""
|
|
175
|
-
logger.info("Starting zendesk_get_articles")
|
|
176
|
-
|
|
177
|
-
ZENDESK_LOCALE = os.getenv("ZENDESK_ARTICLE_LOCALE")
|
|
178
|
-
ZENDESK_SUBDOMAIN = os.getenv("ZENDESK_SUBDOMAIN_ARTICLE")
|
|
179
|
-
logger.debug(f"Using locale: {ZENDESK_LOCALE}, subdomain: {ZENDESK_SUBDOMAIN}")
|
|
180
|
-
|
|
181
|
-
BASE_URL = f"https://{ZENDESK_SUBDOMAIN}.zendesk.com"
|
|
182
|
-
url = f"{BASE_URL}/api/v2/help_center/{ZENDESK_LOCALE}/articles.json"
|
|
183
|
-
logger.debug(f"Request URL: {url}")
|
|
184
|
-
|
|
185
|
-
with httpx.Client(headers=_get_headers(), timeout=30.0) as client:
|
|
186
|
-
logger.debug("Created HTTP client for Zendesk API")
|
|
187
|
-
|
|
188
|
-
try:
|
|
189
|
-
logger.debug("Making GET request for articles")
|
|
190
|
-
response = client.get(url)
|
|
191
|
-
response.raise_for_status()
|
|
192
|
-
logger.debug(f"Successfully received response with status: {response.status_code}")
|
|
193
|
-
|
|
194
|
-
articles = response.json()["articles"]
|
|
195
|
-
logger.info(f"Successfully retrieved {len(articles)} articles")
|
|
196
|
-
return articles
|
|
197
|
-
|
|
198
|
-
except Exception as e:
|
|
199
|
-
logger.error(f"Error fetching articles: {e}")
|
|
200
|
-
raise
|
|
201
|
-
|
|
202
|
-
@mcp.tool()
|
|
203
|
-
def zendesk_get_articles_count() -> int:
|
|
204
|
-
"""Count every Help-Center article in the configured locale.
|
|
205
|
-
|
|
206
|
-
Uses cursor pagination (page[size]=100) because it’s faster and
|
|
207
|
-
has no 10 000-record ceiling. Falls back to offset pagination
|
|
208
|
-
if the account hasn’t been migrated yet.
|
|
209
|
-
"""
|
|
210
|
-
ZENDESK_LOCALE = os.getenv("ZENDESK_ARTICLE_LOCALE") # e.g. "en-us"
|
|
211
|
-
ZENDESK_SUBDOMAIN = os.getenv("ZENDESK_SUBDOMAIN_ARTICLE")
|
|
212
|
-
BASE_URL = f"https://{ZENDESK_SUBDOMAIN}.zendesk.com"
|
|
213
|
-
url = (
|
|
214
|
-
f"{BASE_URL}/api/v2/help_center/{ZENDESK_LOCALE}/articles.json"
|
|
215
|
-
"?page[size]=100" # max page size for HC APIs
|
|
216
|
-
)
|
|
217
|
-
|
|
218
|
-
total = 0
|
|
219
|
-
with httpx.Client(headers=_get_headers(), timeout=30.0) as client:
|
|
220
|
-
while url:
|
|
221
|
-
resp = client.get(url)
|
|
222
|
-
resp.raise_for_status()
|
|
223
|
-
data = resp.json()
|
|
224
|
-
|
|
225
|
-
total += len(data.get("articles", []))
|
|
226
|
-
print(f"Locale: {ZENDESK_LOCALE}")
|
|
227
|
-
print(f"Number of articles: {total}")
|
|
228
|
-
|
|
229
|
-
# Cursor pagination (preferred)
|
|
230
|
-
if data.get("meta", {}).get("has_more"):
|
|
231
|
-
url = data.get("links", {}).get("next")
|
|
232
|
-
continue
|
|
233
|
-
|
|
234
|
-
# Offset pagination fallback
|
|
235
|
-
url = data.get("next_page")
|
|
236
|
-
|
|
237
|
-
return total
|
|
238
|
-
|
|
239
|
-
@mcp.tool()
|
|
240
|
-
def zendesk_search_articles(query: str) -> list[dict]:
|
|
241
|
-
"""Search Zendesk Help Center articles using a query string."""
|
|
242
|
-
logger.info(f"Starting zendesk_search_articles with query: '{query}'")
|
|
243
|
-
|
|
244
|
-
ZENDESK_LOCALE = os.getenv("ZENDESK_ARTICLE_LOCALE") # e.g., "en-us"
|
|
245
|
-
ZENDESK_SUBDOMAIN = os.getenv("ZENDESK_SUBDOMAIN_ARTICLE")
|
|
246
|
-
logger.debug(f"Using locale: {ZENDESK_LOCALE}, subdomain: {ZENDESK_SUBDOMAIN}")
|
|
247
|
-
|
|
248
|
-
BASE_URL = f"https://{ZENDESK_SUBDOMAIN}.zendesk.com"
|
|
249
|
-
url = f"{BASE_URL}/api/v2/help_center/articles/search.json"
|
|
250
|
-
logger.debug(f"Search URL: {url}")
|
|
251
|
-
|
|
252
|
-
params = {
|
|
253
|
-
"query": query,
|
|
254
|
-
"locale": ZENDESK_LOCALE,
|
|
255
|
-
"sort_by": "updated_at",
|
|
256
|
-
"sort_order": "desc",
|
|
257
|
-
}
|
|
258
|
-
logger.debug(f"Search parameters: {params}")
|
|
259
|
-
|
|
260
|
-
with httpx.Client(headers=_get_headers(), timeout=30.0) as client:
|
|
261
|
-
logger.debug("Created HTTP client for Zendesk API")
|
|
262
|
-
|
|
263
|
-
try:
|
|
264
|
-
logger.debug(f"Making GET request to search articles with query: '{query}'")
|
|
265
|
-
response = client.get(url, params=params)
|
|
266
|
-
response.raise_for_status()
|
|
267
|
-
logger.debug(f"Successfully received response with status: {response.status_code}")
|
|
268
|
-
|
|
269
|
-
results = response.json().get("results", [])
|
|
270
|
-
logger.info(f"Search completed successfully, found {len(results)} articles matching query: '{query}'")
|
|
271
|
-
return results
|
|
272
|
-
|
|
273
|
-
except Exception as e:
|
|
274
|
-
logger.error(f"Error searching articles with query '{query}': {e}")
|
|
275
|
-
raise
|
|
276
|
-
|
|
277
|
-
@mcp.tool()
|
|
278
|
-
def zendesk_add_comment_to_ticket(ticket_id: str, comment_body: str, public: bool = False) -> dict:
|
|
279
|
-
"""Add a comment to a Zendesk ticket.
|
|
280
|
-
|
|
281
|
-
Updates the ticket with a new comment via Zendesk Ticketing API:
|
|
282
|
-
PUT /api/v2/tickets/{ticket_id}.json
|
|
283
|
-
"""
|
|
284
|
-
logger.info(f"Starting zendesk_add_comment_to_ticket for ticket_id: {ticket_id}, public: {public}")
|
|
285
|
-
logger.debug(f"Comment body length: {len(comment_body)} characters")
|
|
286
|
-
|
|
287
|
-
ZENDESK_SUBDOMAIN = os.getenv("ZENDESK_SUBDOMAIN_TICKET")
|
|
288
|
-
logger.debug(f"Using Zendesk subdomain: {ZENDESK_SUBDOMAIN}")
|
|
289
|
-
|
|
290
|
-
BASE_URL = f"https://{ZENDESK_SUBDOMAIN}.zendesk.com"
|
|
291
|
-
url = f"{BASE_URL}/api/v2/tickets/{ticket_id}.json"
|
|
292
|
-
logger.debug(f"Request URL: {url}")
|
|
293
|
-
|
|
294
|
-
payload = {
|
|
295
|
-
"ticket": {
|
|
296
|
-
"comment": {
|
|
297
|
-
"body": comment_body,
|
|
298
|
-
"public": public,
|
|
299
|
-
}
|
|
300
|
-
}
|
|
301
|
-
}
|
|
302
|
-
logger.debug(f"Payload prepared for ticket {ticket_id}")
|
|
303
|
-
|
|
304
|
-
import httpx
|
|
305
|
-
with httpx.Client(headers=_get_headers(), timeout=30.0) as client:
|
|
306
|
-
logger.debug("Created HTTP client for Zendesk API")
|
|
307
|
-
|
|
308
|
-
try:
|
|
309
|
-
logger.debug(f"Making PUT request to add comment to ticket {ticket_id}")
|
|
310
|
-
response = client.put(url, json=payload)
|
|
311
|
-
response.raise_for_status()
|
|
312
|
-
logger.debug(f"Successfully received response with status: {response.status_code}")
|
|
313
|
-
|
|
314
|
-
ticket_data = response.json()["ticket"]
|
|
315
|
-
logger.info(f"Successfully added comment to ticket {ticket_id}")
|
|
316
|
-
return ticket_data
|
|
317
|
-
|
|
318
|
-
except Exception as e:
|
|
319
|
-
logger.error(f"Error adding comment to ticket {ticket_id}: {e}")
|
|
320
|
-
raise
|
|
321
|
-
|
|
322
|
-
@mcp.tool()
|
|
323
|
-
def zendesk_set_ticket_custom_field(
|
|
324
|
-
ticket_id: str, custom_field_id: int, custom_field_value: str
|
|
325
|
-
) -> dict:
|
|
326
|
-
"""Set the custom field value of a Zendesk ticket.
|
|
327
|
-
|
|
328
|
-
Uses Zendesk's Update Ticket API to set a custom field value:
|
|
329
|
-
PUT /api/v2/tickets/{ticket_id}.json
|
|
330
|
-
"""#
|
|
331
|
-
logger.info(f"Starting zendesk_set_ticket_custom_field for ticket_id: {ticket_id}, field_id: {custom_field_id}")
|
|
332
|
-
logger.info(f"Custom field value: {custom_field_value}")
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
custom_field_value = [custom_field_value]
|
|
336
|
-
logger.debug("Converted custom field value to list for multi-option field")
|
|
337
|
-
|
|
338
|
-
ZENDESK_SUBDOMAIN = os.getenv("ZENDESK_SUBDOMAIN_TICKET")
|
|
339
|
-
logger.debug(f"Using Zendesk subdomain: {ZENDESK_SUBDOMAIN}")
|
|
340
|
-
|
|
341
|
-
BASE_URL = f"https://{ZENDESK_SUBDOMAIN}.zendesk.com"
|
|
342
|
-
url = f"{BASE_URL}/api/v2/tickets/{ticket_id}.json"
|
|
343
|
-
logger.debug(f"Request URL: {url}")
|
|
344
|
-
|
|
345
|
-
payload = {
|
|
346
|
-
"ticket": {
|
|
347
|
-
"custom_fields": [
|
|
348
|
-
{
|
|
349
|
-
"id": custom_field_id,
|
|
350
|
-
"value": custom_field_value
|
|
351
|
-
}
|
|
352
|
-
]
|
|
353
|
-
}
|
|
354
|
-
}
|
|
355
|
-
logger.debug(f"Payload prepared for ticket {ticket_id} with custom field {custom_field_id}")
|
|
356
|
-
|
|
357
|
-
import httpx
|
|
358
|
-
|
|
359
|
-
with httpx.Client(headers=_get_headers(), timeout=30.0) as client:
|
|
360
|
-
logger.debug("Created HTTP client for Zendesk API")
|
|
361
|
-
|
|
362
|
-
try:
|
|
363
|
-
logger.debug(f"Making PUT request to set custom field {custom_field_id} on ticket {ticket_id}")
|
|
364
|
-
response = client.put(url, json=payload)
|
|
365
|
-
response.raise_for_status()
|
|
366
|
-
logger.debug(f"Successfully received response with status: {response.status_code}")
|
|
367
|
-
|
|
368
|
-
ticket_data = response.json()["ticket"]
|
|
369
|
-
logger.info(f"Successfully set custom field {custom_field_id} on ticket {ticket_id}")
|
|
370
|
-
return ticket_data
|
|
371
|
-
|
|
372
|
-
except Exception as e:
|
|
373
|
-
logger.error(f"Error setting custom field {custom_field_id} on ticket {ticket_id}: {e}")
|
|
374
|
-
raise
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
@mcp.tool()
|
|
379
|
-
def zendesk_set_ticket_tags(ticket_id: str, tags: list[str]) -> list[str]:
|
|
380
|
-
"""Set the complete tag list for a ticket (overwrites existing tags)."""
|
|
381
|
-
logger.info(f"Starting zendesk_set_ticket_tags for ticket_id: {ticket_id}")
|
|
382
|
-
logger.debug(f"Setting tags: {tags} (total: {len(tags)} tags)")
|
|
383
|
-
|
|
384
|
-
ZENDESK_SUBDOMAIN = os.getenv("ZENDESK_SUBDOMAIN_TICKET")
|
|
385
|
-
logger.debug(f"Using Zendesk subdomain: {ZENDESK_SUBDOMAIN}")
|
|
386
|
-
|
|
387
|
-
BASE_URL = f"https://{ZENDESK_SUBDOMAIN}.zendesk.com"
|
|
388
|
-
url = f"{BASE_URL}/api/v2/tickets/{ticket_id}/tags.json"
|
|
389
|
-
logger.debug(f"Request URL: {url}")
|
|
390
|
-
|
|
391
|
-
payload = {"tags": tags}
|
|
392
|
-
logger.debug(f"Payload prepared for ticket {ticket_id}")
|
|
393
|
-
|
|
394
|
-
import httpx
|
|
395
|
-
|
|
396
|
-
with httpx.Client(headers=_get_headers(), timeout=30.0) as client:
|
|
397
|
-
logger.debug("Created HTTP client for Zendesk API")
|
|
398
|
-
|
|
399
|
-
try:
|
|
400
|
-
logger.debug(f"Making PUT request to set tags on ticket {ticket_id}")
|
|
401
|
-
resp = client.put(url, json=payload)
|
|
402
|
-
resp.raise_for_status()
|
|
403
|
-
logger.debug(f"Successfully received response with status: {resp.status_code}")
|
|
404
|
-
|
|
405
|
-
result_tags = resp.json().get("tags", [])
|
|
406
|
-
logger.info(f"Successfully set {len(result_tags)} tags on ticket {ticket_id}")
|
|
407
|
-
return result_tags
|
|
408
|
-
|
|
409
|
-
except Exception as e:
|
|
410
|
-
logger.error(f"Error setting tags on ticket {ticket_id}: {e}")
|
|
411
|
-
raise
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
@mcp.tool()
|
|
415
|
-
def zendesk_add_ticket_tags(ticket_id: str, tags: list[str]) -> list[str]:
|
|
416
|
-
"""Add tags to a ticket (preserves existing tags)."""
|
|
417
|
-
logger.info(f"Starting zendesk_add_ticket_tags for ticket_id: {ticket_id}")
|
|
418
|
-
logger.debug(f"Adding tags: {tags} (total: {len(tags)} tags)")
|
|
419
|
-
|
|
420
|
-
ZENDESK_SUBDOMAIN = os.getenv("ZENDESK_SUBDOMAIN_TICKET")
|
|
421
|
-
logger.debug(f"Using Zendesk subdomain: {ZENDESK_SUBDOMAIN}")
|
|
422
|
-
|
|
423
|
-
BASE_URL = f"https://{ZENDESK_SUBDOMAIN}.zendesk.com"
|
|
424
|
-
url = f"{BASE_URL}/api/v2/tickets/{ticket_id}/tags.json"
|
|
425
|
-
logger.debug(f"Request URL: {url}")
|
|
426
|
-
|
|
427
|
-
payload = {"tags": tags}
|
|
428
|
-
logger.debug(f"Payload prepared for ticket {ticket_id}")
|
|
429
|
-
|
|
430
|
-
import httpx
|
|
431
|
-
|
|
432
|
-
with httpx.Client(headers=_get_headers(), timeout=30.0) as client:
|
|
433
|
-
logger.debug("Created HTTP client for Zendesk API")
|
|
434
|
-
|
|
435
|
-
try:
|
|
436
|
-
logger.debug(f"Making POST request to add tags to ticket {ticket_id}")
|
|
437
|
-
resp = client.post(url, json=payload)
|
|
438
|
-
resp.raise_for_status()
|
|
439
|
-
logger.debug(f"Successfully received response with status: {resp.status_code}")
|
|
440
|
-
|
|
441
|
-
result_tags = resp.json().get("tags", [])
|
|
442
|
-
logger.info(f"Successfully added tags to ticket {ticket_id}, total tags now: {len(result_tags)}")
|
|
443
|
-
return result_tags
|
|
444
|
-
|
|
445
|
-
except Exception as e:
|
|
446
|
-
logger.error(f"Error adding tags to ticket {ticket_id}: {e}")
|
|
447
|
-
raise
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
@mcp.tool()
|
|
451
|
-
def zendesk_get_ticket_field_type(field_id: int) -> dict:
|
|
452
|
-
"""Return the Zendesk custom field type and options for a field id.
|
|
453
|
-
|
|
454
|
-
Uses GET /api/v2/ticket_fields/{field_id}.json.
|
|
455
|
-
|
|
456
|
-
Returns a dict containing at least:
|
|
457
|
-
{ "type": str, "custom_field_options": list }
|
|
458
|
-
"""
|
|
459
|
-
logger.info(f"Starting zendesk_get_ticket_field_type for field_id: {field_id}")
|
|
460
|
-
|
|
461
|
-
ZENDESK_SUBDOMAIN = os.getenv("ZENDESK_SUBDOMAIN_TICKET")
|
|
462
|
-
logger.debug(f"Using Zendesk subdomain: {ZENDESK_SUBDOMAIN}")
|
|
463
|
-
|
|
464
|
-
BASE_URL = f"https://{ZENDESK_SUBDOMAIN}.zendesk.com"
|
|
465
|
-
url = f"{BASE_URL}/api/v2/ticket_fields/{field_id}.json"
|
|
466
|
-
logger.debug(f"Request URL: {url}")
|
|
467
|
-
|
|
468
|
-
import httpx
|
|
469
|
-
|
|
470
|
-
with httpx.Client(headers=_get_headers(), timeout=30.0) as client:
|
|
471
|
-
logger.debug("Created HTTP client for Zendesk API")
|
|
472
|
-
|
|
473
|
-
try:
|
|
474
|
-
logger.debug(f"Making GET request for ticket field {field_id}")
|
|
475
|
-
resp = client.get(url)
|
|
476
|
-
resp.raise_for_status()
|
|
477
|
-
logger.debug(f"Successfully received response with status: {resp.status_code}")
|
|
478
|
-
|
|
479
|
-
field = resp.json().get("ticket_field", {})
|
|
480
|
-
result = {
|
|
481
|
-
"id": field.get("id"),
|
|
482
|
-
"type": field.get("type"),
|
|
483
|
-
"title": field.get("title"),
|
|
484
|
-
"required": field.get("required"),
|
|
485
|
-
"custom_field_options": field.get("custom_field_options", []),
|
|
486
|
-
}
|
|
487
|
-
|
|
488
|
-
logger.info(f"Successfully retrieved field info for {field_id}: type={result['type']}, title='{result['title']}'")
|
|
489
|
-
logger.debug(f"Field has {len(result['custom_field_options'])} custom options")
|
|
490
|
-
return result
|
|
491
|
-
|
|
492
|
-
except Exception as e:
|
|
493
|
-
logger.error(f"Error fetching ticket field {field_id}: {e}")
|
|
494
|
-
raise
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
if __name__ == "__main__":
|
|
500
|
-
transport = os.getenv("ZENDESK_MCP_TRANSPORT", "stdio")
|
|
501
|
-
mcp.run(transport=transport)
|
flock/webapp/__init__.py
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
"""Flock Web Application Package."""
|
flock/webapp/app/__init__.py
DELETED
|
File without changes
|
flock/webapp/app/api/__init__.py
DELETED
|
File without changes
|