flock-core 0.5.0b28__py3-none-any.whl → 0.5.0b51__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.

Files changed (469) hide show
  1. flock/__init__.py +12 -217
  2. flock/agent.py +678 -0
  3. flock/api/themes.py +71 -0
  4. flock/artifacts.py +79 -0
  5. flock/cli.py +75 -0
  6. flock/components.py +173 -0
  7. flock/dashboard/__init__.py +28 -0
  8. flock/dashboard/collector.py +283 -0
  9. flock/dashboard/events.py +182 -0
  10. flock/dashboard/launcher.py +230 -0
  11. flock/dashboard/service.py +537 -0
  12. flock/dashboard/websocket.py +235 -0
  13. flock/engines/__init__.py +6 -0
  14. flock/engines/dspy_engine.py +856 -0
  15. flock/examples.py +128 -0
  16. flock/frontend/README.md +678 -0
  17. flock/frontend/docs/DESIGN_SYSTEM.md +1980 -0
  18. flock/frontend/index.html +12 -0
  19. flock/frontend/package-lock.json +4347 -0
  20. flock/frontend/package.json +48 -0
  21. flock/frontend/src/App.tsx +79 -0
  22. flock/frontend/src/__tests__/e2e/critical-scenarios.test.tsx +587 -0
  23. flock/frontend/src/__tests__/integration/filtering-e2e.test.tsx +387 -0
  24. flock/frontend/src/__tests__/integration/graph-rendering.test.tsx +640 -0
  25. flock/frontend/src/__tests__/integration/indexeddb-persistence.test.tsx +699 -0
  26. flock/frontend/src/components/common/BuildInfo.tsx +39 -0
  27. flock/frontend/src/components/common/EmptyState.module.css +115 -0
  28. flock/frontend/src/components/common/EmptyState.tsx +128 -0
  29. flock/frontend/src/components/common/ErrorBoundary.module.css +169 -0
  30. flock/frontend/src/components/common/ErrorBoundary.tsx +118 -0
  31. flock/frontend/src/components/common/KeyboardShortcutsDialog.css +251 -0
  32. flock/frontend/src/components/common/KeyboardShortcutsDialog.tsx +151 -0
  33. flock/frontend/src/components/common/LoadingSpinner.module.css +97 -0
  34. flock/frontend/src/components/common/LoadingSpinner.tsx +29 -0
  35. flock/frontend/src/components/controls/PublishControl.css +547 -0
  36. flock/frontend/src/components/controls/PublishControl.test.tsx +543 -0
  37. flock/frontend/src/components/controls/PublishControl.tsx +432 -0
  38. flock/frontend/src/components/details/DetailWindowContainer.tsx +62 -0
  39. flock/frontend/src/components/details/LiveOutputTab.test.tsx +792 -0
  40. flock/frontend/src/components/details/LiveOutputTab.tsx +220 -0
  41. flock/frontend/src/components/details/MessageHistoryTab.tsx +299 -0
  42. flock/frontend/src/components/details/NodeDetailWindow.test.tsx +501 -0
  43. flock/frontend/src/components/details/NodeDetailWindow.tsx +218 -0
  44. flock/frontend/src/components/details/RunStatusTab.tsx +307 -0
  45. flock/frontend/src/components/details/tabs.test.tsx +1015 -0
  46. flock/frontend/src/components/filters/CorrelationIDFilter.module.css +102 -0
  47. flock/frontend/src/components/filters/CorrelationIDFilter.test.tsx +197 -0
  48. flock/frontend/src/components/filters/CorrelationIDFilter.tsx +121 -0
  49. flock/frontend/src/components/filters/FilterBar.module.css +29 -0
  50. flock/frontend/src/components/filters/FilterBar.test.tsx +133 -0
  51. flock/frontend/src/components/filters/FilterBar.tsx +33 -0
  52. flock/frontend/src/components/filters/FilterPills.module.css +79 -0
  53. flock/frontend/src/components/filters/FilterPills.test.tsx +173 -0
  54. flock/frontend/src/components/filters/FilterPills.tsx +67 -0
  55. flock/frontend/src/components/filters/TimeRangeFilter.module.css +91 -0
  56. flock/frontend/src/components/filters/TimeRangeFilter.test.tsx +154 -0
  57. flock/frontend/src/components/filters/TimeRangeFilter.tsx +105 -0
  58. flock/frontend/src/components/graph/AgentNode.test.tsx +75 -0
  59. flock/frontend/src/components/graph/AgentNode.tsx +322 -0
  60. flock/frontend/src/components/graph/GraphCanvas.tsx +406 -0
  61. flock/frontend/src/components/graph/MessageFlowEdge.tsx +128 -0
  62. flock/frontend/src/components/graph/MessageNode.test.tsx +62 -0
  63. flock/frontend/src/components/graph/MessageNode.tsx +116 -0
  64. flock/frontend/src/components/graph/MiniMap.tsx +47 -0
  65. flock/frontend/src/components/graph/TransformEdge.tsx +123 -0
  66. flock/frontend/src/components/layout/DashboardLayout.css +407 -0
  67. flock/frontend/src/components/layout/DashboardLayout.tsx +300 -0
  68. flock/frontend/src/components/layout/Header.module.css +88 -0
  69. flock/frontend/src/components/layout/Header.tsx +52 -0
  70. flock/frontend/src/components/modules/EventLogModule.test.tsx +401 -0
  71. flock/frontend/src/components/modules/EventLogModule.tsx +396 -0
  72. flock/frontend/src/components/modules/EventLogModuleWrapper.tsx +17 -0
  73. flock/frontend/src/components/modules/ModuleRegistry.test.ts +333 -0
  74. flock/frontend/src/components/modules/ModuleRegistry.ts +85 -0
  75. flock/frontend/src/components/modules/ModuleWindow.tsx +155 -0
  76. flock/frontend/src/components/modules/registerModules.ts +20 -0
  77. flock/frontend/src/components/settings/AdvancedSettings.tsx +175 -0
  78. flock/frontend/src/components/settings/AppearanceSettings.tsx +185 -0
  79. flock/frontend/src/components/settings/GraphSettings.tsx +110 -0
  80. flock/frontend/src/components/settings/SettingsPanel.css +327 -0
  81. flock/frontend/src/components/settings/SettingsPanel.tsx +131 -0
  82. flock/frontend/src/components/settings/ThemeSelector.tsx +298 -0
  83. flock/frontend/src/hooks/useKeyboardShortcuts.ts +148 -0
  84. flock/frontend/src/hooks/useModulePersistence.test.ts +442 -0
  85. flock/frontend/src/hooks/useModulePersistence.ts +154 -0
  86. flock/frontend/src/hooks/useModules.ts +139 -0
  87. flock/frontend/src/hooks/usePersistence.ts +139 -0
  88. flock/frontend/src/main.tsx +13 -0
  89. flock/frontend/src/services/api.ts +213 -0
  90. flock/frontend/src/services/indexeddb.test.ts +793 -0
  91. flock/frontend/src/services/indexeddb.ts +794 -0
  92. flock/frontend/src/services/layout.test.ts +437 -0
  93. flock/frontend/src/services/layout.ts +146 -0
  94. flock/frontend/src/services/themeApplicator.ts +140 -0
  95. flock/frontend/src/services/themeService.ts +77 -0
  96. flock/frontend/src/services/websocket.test.ts +595 -0
  97. flock/frontend/src/services/websocket.ts +685 -0
  98. flock/frontend/src/store/filterStore.test.ts +242 -0
  99. flock/frontend/src/store/filterStore.ts +103 -0
  100. flock/frontend/src/store/graphStore.test.ts +186 -0
  101. flock/frontend/src/store/graphStore.ts +414 -0
  102. flock/frontend/src/store/moduleStore.test.ts +253 -0
  103. flock/frontend/src/store/moduleStore.ts +57 -0
  104. flock/frontend/src/store/settingsStore.ts +188 -0
  105. flock/frontend/src/store/streamStore.ts +68 -0
  106. flock/frontend/src/store/uiStore.test.ts +54 -0
  107. flock/frontend/src/store/uiStore.ts +110 -0
  108. flock/frontend/src/store/wsStore.ts +34 -0
  109. flock/frontend/src/styles/index.css +15 -0
  110. flock/frontend/src/styles/scrollbar.css +47 -0
  111. flock/frontend/src/styles/variables.css +488 -0
  112. flock/frontend/src/test/setup.ts +1 -0
  113. flock/frontend/src/types/filters.ts +14 -0
  114. flock/frontend/src/types/graph.ts +55 -0
  115. flock/frontend/src/types/modules.ts +7 -0
  116. flock/frontend/src/types/theme.ts +55 -0
  117. flock/frontend/src/utils/mockData.ts +85 -0
  118. flock/frontend/src/utils/performance.ts +16 -0
  119. flock/frontend/src/utils/transforms.test.ts +860 -0
  120. flock/frontend/src/utils/transforms.ts +323 -0
  121. flock/frontend/src/vite-env.d.ts +17 -0
  122. flock/frontend/tsconfig.json +27 -0
  123. flock/frontend/tsconfig.node.json +11 -0
  124. flock/frontend/vite.config.ts +25 -0
  125. flock/frontend/vitest.config.ts +11 -0
  126. flock/{core/util → helper}/cli_helper.py +4 -3
  127. flock/{core/logging → logging}/__init__.py +2 -3
  128. flock/{core/logging → logging}/formatters/enum_builder.py +3 -4
  129. flock/{core/logging → logging}/formatters/theme_builder.py +19 -44
  130. flock/{core/logging → logging}/formatters/themed_formatter.py +69 -115
  131. flock/{core/logging → logging}/logging.py +77 -61
  132. flock/{core/logging → logging}/telemetry.py +20 -26
  133. flock/{core/logging → logging}/telemetry_exporter/base_exporter.py +2 -2
  134. flock/{core/logging → logging}/telemetry_exporter/file_exporter.py +6 -9
  135. flock/{core/logging → logging}/telemetry_exporter/sqlite_exporter.py +2 -3
  136. flock/{core/logging → logging}/trace_and_logged.py +20 -24
  137. flock/mcp/__init__.py +91 -0
  138. flock/{core/mcp/mcp_client.py → mcp/client.py} +103 -154
  139. flock/{core/mcp/mcp_config.py → mcp/config.py} +62 -117
  140. flock/mcp/manager.py +255 -0
  141. flock/mcp/servers/sse/__init__.py +1 -1
  142. flock/mcp/servers/sse/flock_sse_server.py +11 -53
  143. flock/mcp/servers/stdio/__init__.py +1 -1
  144. flock/mcp/servers/stdio/flock_stdio_server.py +8 -48
  145. flock/mcp/servers/streamable_http/flock_streamable_http_server.py +17 -62
  146. flock/mcp/servers/websockets/flock_websocket_server.py +7 -40
  147. flock/{core/mcp/flock_mcp_tool.py → mcp/tool.py} +16 -26
  148. flock/mcp/types/__init__.py +42 -0
  149. flock/{core/mcp → mcp}/types/callbacks.py +9 -15
  150. flock/{core/mcp → mcp}/types/factories.py +7 -6
  151. flock/{core/mcp → mcp}/types/handlers.py +13 -18
  152. flock/{core/mcp → mcp}/types/types.py +70 -74
  153. flock/{core/mcp → mcp}/util/helpers.py +1 -1
  154. flock/orchestrator.py +645 -0
  155. flock/registry.py +148 -0
  156. flock/runtime.py +262 -0
  157. flock/service.py +140 -0
  158. flock/store.py +69 -0
  159. flock/subscription.py +111 -0
  160. flock/themes/andromeda.toml +1 -1
  161. flock/themes/apple-system-colors.toml +1 -1
  162. flock/themes/arcoiris.toml +1 -1
  163. flock/themes/atomonelight.toml +1 -1
  164. flock/themes/ayu copy.toml +1 -1
  165. flock/themes/ayu-light.toml +1 -1
  166. flock/themes/belafonte-day.toml +1 -1
  167. flock/themes/belafonte-night.toml +1 -1
  168. flock/themes/blulocodark.toml +1 -1
  169. flock/themes/breeze.toml +1 -1
  170. flock/themes/broadcast.toml +1 -1
  171. flock/themes/brogrammer.toml +1 -1
  172. flock/themes/builtin-dark.toml +1 -1
  173. flock/themes/builtin-pastel-dark.toml +1 -1
  174. flock/themes/catppuccin-latte.toml +1 -1
  175. flock/themes/catppuccin-macchiato.toml +1 -1
  176. flock/themes/catppuccin-mocha.toml +1 -1
  177. flock/themes/cga.toml +1 -1
  178. flock/themes/chalk.toml +1 -1
  179. flock/themes/ciapre.toml +1 -1
  180. flock/themes/coffee-theme.toml +1 -1
  181. flock/themes/cyberpunkscarletprotocol.toml +1 -1
  182. flock/themes/dark+.toml +1 -1
  183. flock/themes/darkermatrix.toml +1 -1
  184. flock/themes/darkside.toml +1 -1
  185. flock/themes/desert.toml +1 -1
  186. flock/themes/django.toml +1 -1
  187. flock/themes/djangosmooth.toml +1 -1
  188. flock/themes/doomone.toml +1 -1
  189. flock/themes/dotgov.toml +1 -1
  190. flock/themes/dracula+.toml +1 -1
  191. flock/themes/duckbones.toml +1 -1
  192. flock/themes/encom.toml +1 -1
  193. flock/themes/espresso.toml +1 -1
  194. flock/themes/everblush.toml +1 -1
  195. flock/themes/fairyfloss.toml +1 -1
  196. flock/themes/fideloper.toml +1 -1
  197. flock/themes/fishtank.toml +1 -1
  198. flock/themes/flexoki-light.toml +1 -1
  199. flock/themes/floraverse.toml +1 -1
  200. flock/themes/framer.toml +1 -1
  201. flock/themes/galizur.toml +1 -1
  202. flock/themes/github.toml +1 -1
  203. flock/themes/grass.toml +1 -1
  204. flock/themes/grey-green.toml +1 -1
  205. flock/themes/gruvboxlight.toml +1 -1
  206. flock/themes/guezwhoz.toml +1 -1
  207. flock/themes/harper.toml +1 -1
  208. flock/themes/hax0r-blue.toml +1 -1
  209. flock/themes/hopscotch.256.toml +1 -1
  210. flock/themes/ic-green-ppl.toml +1 -1
  211. flock/themes/iceberg-dark.toml +1 -1
  212. flock/themes/japanesque.toml +1 -1
  213. flock/themes/jubi.toml +1 -1
  214. flock/themes/kibble.toml +1 -1
  215. flock/themes/kolorit.toml +1 -1
  216. flock/themes/kurokula.toml +1 -1
  217. flock/themes/materialdesigncolors.toml +1 -1
  218. flock/themes/matrix.toml +1 -1
  219. flock/themes/mellifluous.toml +1 -1
  220. flock/themes/midnight-in-mojave.toml +1 -1
  221. flock/themes/monokai-remastered.toml +1 -1
  222. flock/themes/monokai-soda.toml +1 -1
  223. flock/themes/neon.toml +1 -1
  224. flock/themes/neopolitan.toml +1 -1
  225. flock/themes/nord-light.toml +1 -1
  226. flock/themes/ocean.toml +1 -1
  227. flock/themes/onehalfdark.toml +1 -1
  228. flock/themes/onehalflight.toml +1 -1
  229. flock/themes/palenighthc.toml +1 -1
  230. flock/themes/paulmillr.toml +1 -1
  231. flock/themes/pencildark.toml +1 -1
  232. flock/themes/pnevma.toml +1 -1
  233. flock/themes/purple-rain.toml +1 -1
  234. flock/themes/purplepeter.toml +1 -1
  235. flock/themes/raycast-dark.toml +1 -1
  236. flock/themes/red-sands.toml +1 -1
  237. flock/themes/relaxed.toml +1 -1
  238. flock/themes/retro.toml +1 -1
  239. flock/themes/rose-pine.toml +1 -1
  240. flock/themes/royal.toml +1 -1
  241. flock/themes/ryuuko.toml +1 -1
  242. flock/themes/sakura.toml +1 -1
  243. flock/themes/scarlet-protocol.toml +1 -1
  244. flock/themes/seoulbones-dark.toml +1 -1
  245. flock/themes/shades-of-purple.toml +1 -1
  246. flock/themes/smyck.toml +1 -1
  247. flock/themes/softserver.toml +1 -1
  248. flock/themes/solarized-darcula.toml +1 -1
  249. flock/themes/square.toml +1 -1
  250. flock/themes/sugarplum.toml +1 -1
  251. flock/themes/thayer-bright.toml +1 -1
  252. flock/themes/tokyonight.toml +1 -1
  253. flock/themes/tomorrow.toml +1 -1
  254. flock/themes/ubuntu.toml +1 -1
  255. flock/themes/ultradark.toml +1 -1
  256. flock/themes/ultraviolent.toml +1 -1
  257. flock/themes/unikitty.toml +1 -1
  258. flock/themes/urple.toml +1 -1
  259. flock/themes/vesper.toml +1 -1
  260. flock/themes/vimbones.toml +1 -1
  261. flock/themes/wildcherry.toml +1 -1
  262. flock/themes/wilmersdorf.toml +1 -1
  263. flock/themes/wryan.toml +1 -1
  264. flock/themes/xcodedarkhc.toml +1 -1
  265. flock/themes/xcodelight.toml +1 -1
  266. flock/themes/zenbones-light.toml +1 -1
  267. flock/themes/zenwritten-dark.toml +1 -1
  268. flock/utilities.py +301 -0
  269. flock/{components/utility → utility}/output_utility_component.py +68 -53
  270. flock/visibility.py +107 -0
  271. flock_core-0.5.0b51.dist-info/METADATA +747 -0
  272. flock_core-0.5.0b51.dist-info/RECORD +508 -0
  273. flock_core-0.5.0b51.dist-info/entry_points.txt +2 -0
  274. {flock_core-0.5.0b28.dist-info → flock_core-0.5.0b51.dist-info}/licenses/LICENSE +1 -1
  275. flock/adapter/__init__.py +0 -14
  276. flock/adapter/azure_adapter.py +0 -68
  277. flock/adapter/chroma_adapter.py +0 -73
  278. flock/adapter/faiss_adapter.py +0 -97
  279. flock/adapter/pinecone_adapter.py +0 -51
  280. flock/adapter/vector_base.py +0 -47
  281. flock/cli/assets/release_notes.md +0 -140
  282. flock/cli/config.py +0 -8
  283. flock/cli/constants.py +0 -36
  284. flock/cli/create_agent.py +0 -1
  285. flock/cli/create_flock.py +0 -280
  286. flock/cli/execute_flock.py +0 -620
  287. flock/cli/load_agent.py +0 -1
  288. flock/cli/load_examples.py +0 -1
  289. flock/cli/load_flock.py +0 -192
  290. flock/cli/load_release_notes.py +0 -20
  291. flock/cli/loaded_flock_cli.py +0 -254
  292. flock/cli/manage_agents.py +0 -459
  293. flock/cli/registry_management.py +0 -889
  294. flock/cli/runner.py +0 -41
  295. flock/cli/settings.py +0 -857
  296. flock/cli/utils.py +0 -135
  297. flock/cli/view_results.py +0 -29
  298. flock/cli/yaml_editor.py +0 -396
  299. flock/components/__init__.py +0 -30
  300. flock/components/evaluation/__init__.py +0 -9
  301. flock/components/evaluation/declarative_evaluation_component.py +0 -606
  302. flock/components/routing/__init__.py +0 -15
  303. flock/components/routing/conditional_routing_component.py +0 -494
  304. flock/components/routing/default_routing_component.py +0 -103
  305. flock/components/routing/llm_routing_component.py +0 -206
  306. flock/components/utility/__init__.py +0 -22
  307. flock/components/utility/example_utility_component.py +0 -250
  308. flock/components/utility/feedback_utility_component.py +0 -206
  309. flock/components/utility/memory_utility_component.py +0 -550
  310. flock/components/utility/metrics_utility_component.py +0 -700
  311. flock/config.py +0 -61
  312. flock/core/__init__.py +0 -110
  313. flock/core/agent/__init__.py +0 -16
  314. flock/core/agent/default_agent.py +0 -216
  315. flock/core/agent/flock_agent_components.py +0 -104
  316. flock/core/agent/flock_agent_execution.py +0 -101
  317. flock/core/agent/flock_agent_integration.py +0 -260
  318. flock/core/agent/flock_agent_lifecycle.py +0 -186
  319. flock/core/agent/flock_agent_serialization.py +0 -381
  320. flock/core/api/__init__.py +0 -10
  321. flock/core/api/custom_endpoint.py +0 -45
  322. flock/core/api/endpoints.py +0 -254
  323. flock/core/api/main.py +0 -162
  324. flock/core/api/models.py +0 -97
  325. flock/core/api/run_store.py +0 -224
  326. flock/core/api/runner.py +0 -44
  327. flock/core/api/service.py +0 -214
  328. flock/core/component/__init__.py +0 -15
  329. flock/core/component/agent_component_base.py +0 -309
  330. flock/core/component/evaluation_component.py +0 -62
  331. flock/core/component/routing_component.py +0 -74
  332. flock/core/component/utility_component.py +0 -69
  333. flock/core/config/flock_agent_config.py +0 -58
  334. flock/core/config/scheduled_agent_config.py +0 -40
  335. flock/core/context/context.py +0 -213
  336. flock/core/context/context_manager.py +0 -37
  337. flock/core/context/context_vars.py +0 -10
  338. flock/core/evaluation/utils.py +0 -396
  339. flock/core/execution/batch_executor.py +0 -369
  340. flock/core/execution/evaluation_executor.py +0 -438
  341. flock/core/execution/local_executor.py +0 -31
  342. flock/core/execution/opik_executor.py +0 -103
  343. flock/core/execution/temporal_executor.py +0 -164
  344. flock/core/flock.py +0 -634
  345. flock/core/flock_agent.py +0 -336
  346. flock/core/flock_factory.py +0 -613
  347. flock/core/flock_scheduler.py +0 -166
  348. flock/core/flock_server_manager.py +0 -136
  349. flock/core/interpreter/python_interpreter.py +0 -689
  350. flock/core/mcp/__init__.py +0 -1
  351. flock/core/mcp/flock_mcp_server.py +0 -680
  352. flock/core/mcp/mcp_client_manager.py +0 -201
  353. flock/core/mcp/types/__init__.py +0 -1
  354. flock/core/mixin/dspy_integration.py +0 -403
  355. flock/core/mixin/prompt_parser.py +0 -125
  356. flock/core/orchestration/__init__.py +0 -15
  357. flock/core/orchestration/flock_batch_processor.py +0 -94
  358. flock/core/orchestration/flock_evaluator.py +0 -113
  359. flock/core/orchestration/flock_execution.py +0 -295
  360. flock/core/orchestration/flock_initialization.py +0 -149
  361. flock/core/orchestration/flock_server_manager.py +0 -67
  362. flock/core/orchestration/flock_web_server.py +0 -117
  363. flock/core/registry/__init__.py +0 -45
  364. flock/core/registry/agent_registry.py +0 -69
  365. flock/core/registry/callable_registry.py +0 -139
  366. flock/core/registry/component_discovery.py +0 -142
  367. flock/core/registry/component_registry.py +0 -64
  368. flock/core/registry/config_mapping.py +0 -64
  369. flock/core/registry/decorators.py +0 -137
  370. flock/core/registry/registry_hub.py +0 -205
  371. flock/core/registry/server_registry.py +0 -57
  372. flock/core/registry/type_registry.py +0 -86
  373. flock/core/serialization/__init__.py +0 -13
  374. flock/core/serialization/callable_registry.py +0 -52
  375. flock/core/serialization/flock_serializer.py +0 -832
  376. flock/core/serialization/json_encoder.py +0 -41
  377. flock/core/serialization/secure_serializer.py +0 -175
  378. flock/core/serialization/serializable.py +0 -342
  379. flock/core/serialization/serialization_utils.py +0 -412
  380. flock/core/util/file_path_utils.py +0 -223
  381. flock/core/util/hydrator.py +0 -309
  382. flock/core/util/input_resolver.py +0 -164
  383. flock/core/util/loader.py +0 -59
  384. flock/core/util/splitter.py +0 -219
  385. flock/di.py +0 -27
  386. flock/platform/docker_tools.py +0 -49
  387. flock/platform/jaeger_install.py +0 -86
  388. flock/webapp/__init__.py +0 -1
  389. flock/webapp/app/__init__.py +0 -0
  390. flock/webapp/app/api/__init__.py +0 -0
  391. flock/webapp/app/api/agent_management.py +0 -241
  392. flock/webapp/app/api/execution.py +0 -709
  393. flock/webapp/app/api/flock_management.py +0 -129
  394. flock/webapp/app/api/registry_viewer.py +0 -30
  395. flock/webapp/app/chat.py +0 -665
  396. flock/webapp/app/config.py +0 -104
  397. flock/webapp/app/dependencies.py +0 -117
  398. flock/webapp/app/main.py +0 -1070
  399. flock/webapp/app/middleware.py +0 -113
  400. flock/webapp/app/models_ui.py +0 -7
  401. flock/webapp/app/services/__init__.py +0 -0
  402. flock/webapp/app/services/feedback_file_service.py +0 -363
  403. flock/webapp/app/services/flock_service.py +0 -337
  404. flock/webapp/app/services/sharing_models.py +0 -81
  405. flock/webapp/app/services/sharing_store.py +0 -762
  406. flock/webapp/app/templates/theme_mapper.html +0 -326
  407. flock/webapp/app/theme_mapper.py +0 -812
  408. flock/webapp/app/utils.py +0 -85
  409. flock/webapp/run.py +0 -215
  410. flock/webapp/static/css/chat.css +0 -301
  411. flock/webapp/static/css/components.css +0 -167
  412. flock/webapp/static/css/header.css +0 -39
  413. flock/webapp/static/css/layout.css +0 -46
  414. flock/webapp/static/css/sidebar.css +0 -127
  415. flock/webapp/static/css/two-pane.css +0 -48
  416. flock/webapp/templates/base.html +0 -200
  417. flock/webapp/templates/chat.html +0 -152
  418. flock/webapp/templates/chat_settings.html +0 -19
  419. flock/webapp/templates/flock_editor.html +0 -16
  420. flock/webapp/templates/index.html +0 -12
  421. flock/webapp/templates/partials/_agent_detail_form.html +0 -93
  422. flock/webapp/templates/partials/_agent_list.html +0 -18
  423. flock/webapp/templates/partials/_agent_manager_view.html +0 -51
  424. flock/webapp/templates/partials/_agent_tools_checklist.html +0 -14
  425. flock/webapp/templates/partials/_chat_container.html +0 -15
  426. flock/webapp/templates/partials/_chat_messages.html +0 -57
  427. flock/webapp/templates/partials/_chat_settings_form.html +0 -85
  428. flock/webapp/templates/partials/_create_flock_form.html +0 -50
  429. flock/webapp/templates/partials/_dashboard_flock_detail.html +0 -17
  430. flock/webapp/templates/partials/_dashboard_flock_file_list.html +0 -16
  431. flock/webapp/templates/partials/_dashboard_flock_properties_preview.html +0 -28
  432. flock/webapp/templates/partials/_dashboard_upload_flock_form.html +0 -16
  433. flock/webapp/templates/partials/_dynamic_input_form_content.html +0 -22
  434. flock/webapp/templates/partials/_env_vars_table.html +0 -23
  435. flock/webapp/templates/partials/_execution_form.html +0 -118
  436. flock/webapp/templates/partials/_execution_view_container.html +0 -28
  437. flock/webapp/templates/partials/_flock_file_list.html +0 -23
  438. flock/webapp/templates/partials/_flock_properties_form.html +0 -52
  439. flock/webapp/templates/partials/_flock_upload_form.html +0 -16
  440. flock/webapp/templates/partials/_header_flock_status.html +0 -5
  441. flock/webapp/templates/partials/_load_manager_view.html +0 -49
  442. flock/webapp/templates/partials/_registry_table.html +0 -25
  443. flock/webapp/templates/partials/_registry_viewer_content.html +0 -70
  444. flock/webapp/templates/partials/_results_display.html +0 -78
  445. flock/webapp/templates/partials/_settings_env_content.html +0 -9
  446. flock/webapp/templates/partials/_settings_theme_content.html +0 -14
  447. flock/webapp/templates/partials/_settings_view.html +0 -36
  448. flock/webapp/templates/partials/_share_chat_link_snippet.html +0 -11
  449. flock/webapp/templates/partials/_share_link_snippet.html +0 -35
  450. flock/webapp/templates/partials/_sidebar.html +0 -74
  451. flock/webapp/templates/partials/_streaming_results_container.html +0 -195
  452. flock/webapp/templates/partials/_structured_data_view.html +0 -40
  453. flock/webapp/templates/partials/_theme_preview.html +0 -36
  454. flock/webapp/templates/registry_viewer.html +0 -84
  455. flock/webapp/templates/shared_run_page.html +0 -140
  456. flock/workflow/__init__.py +0 -0
  457. flock/workflow/activities.py +0 -196
  458. flock/workflow/agent_activities.py +0 -24
  459. flock/workflow/agent_execution_activity.py +0 -202
  460. flock/workflow/flock_workflow.py +0 -214
  461. flock/workflow/temporal_config.py +0 -96
  462. flock/workflow/temporal_setup.py +0 -68
  463. flock_core-0.5.0b28.dist-info/METADATA +0 -274
  464. flock_core-0.5.0b28.dist-info/RECORD +0 -561
  465. flock_core-0.5.0b28.dist-info/entry_points.txt +0 -2
  466. /flock/{core/logging → logging}/formatters/themes.py +0 -0
  467. /flock/{core/logging → logging}/span_middleware/baggage_span_processor.py +0 -0
  468. /flock/{core/mcp → mcp}/util/__init__.py +0 -0
  469. {flock_core-0.5.0b28.dist-info → flock_core-0.5.0b51.dist-info}/WHEEL +0 -0
@@ -0,0 +1,860 @@
1
+ import { describe, it, expect, beforeEach } from 'vitest';
2
+ import { Edge } from '@xyflow/react';
3
+
4
+ /**
5
+ * Phase 4: Graph Visualization & Dual Views - Edge Derivation Tests
6
+ *
7
+ * Tests for edge derivation algorithms from DATA_MODEL.md:
8
+ * - deriveAgentViewEdges: Creates message flow edges between agents
9
+ * - deriveBlackboardViewEdges: Creates transformation edges between artifacts
10
+ *
11
+ * SPECIFICATION: docs/specs/003-real-time-dashboard/DATA_MODEL.md lines 770-853
12
+ * REFERENCE: docs/specs/003-real-time-dashboard/PLAN.md Phase 4
13
+ */
14
+
15
+ // Type definitions matching DATA_MODEL.md specification
16
+
17
+ interface Artifact {
18
+ artifact_id: string;
19
+ artifact_type: string;
20
+ produced_by: string;
21
+ consumed_by: string[];
22
+ published_at: string; // ISO timestamp
23
+ payload: any;
24
+ correlation_id: string;
25
+ }
26
+
27
+ interface Run {
28
+ run_id: string;
29
+ agent_name: string;
30
+ correlation_id: string; // Groups multiple agent runs together
31
+ status: 'active' | 'completed' | 'error';
32
+ consumed_artifacts: string[];
33
+ produced_artifacts: string[];
34
+ duration_ms?: number;
35
+ }
36
+
37
+ interface DashboardState {
38
+ artifacts: Map<string, Artifact>;
39
+ runs: Map<string, Run>;
40
+ }
41
+
42
+ // Edge type definitions from DATA_MODEL.md lines 805-817
43
+ interface AgentViewEdge extends Edge {
44
+ type: 'message_flow';
45
+ label: string; // Format: "message_type (count)"
46
+ data: {
47
+ message_type: string;
48
+ message_count: number;
49
+ artifact_ids: string[];
50
+ latest_timestamp: string;
51
+ };
52
+ }
53
+
54
+ // Edge type definitions from DATA_MODEL.md lines 836-847
55
+ interface BlackboardViewEdge extends Edge {
56
+ type: 'transformation';
57
+ label: string; // agent_name
58
+ data: {
59
+ transformer_agent: string;
60
+ run_id: string;
61
+ duration_ms?: number;
62
+ };
63
+ }
64
+
65
+ // Function interfaces (to be implemented in transforms.ts)
66
+ interface EdgeTransforms {
67
+ deriveAgentViewEdges(state: DashboardState): AgentViewEdge[];
68
+ deriveBlackboardViewEdges(state: DashboardState): BlackboardViewEdge[];
69
+ }
70
+
71
+ describe('Edge Derivation Algorithms', () => {
72
+ let transforms: EdgeTransforms;
73
+
74
+ beforeEach(() => {
75
+ // Mock implementation that will fail until real implementation
76
+ transforms = {
77
+ deriveAgentViewEdges: () => {
78
+ throw new Error('deriveAgentViewEdges not implemented');
79
+ },
80
+ deriveBlackboardViewEdges: () => {
81
+ throw new Error('deriveBlackboardViewEdges not implemented');
82
+ },
83
+ };
84
+ });
85
+
86
+ describe('deriveAgentViewEdges - Message Flow Edges', () => {
87
+ it('should create edges between agents (source → target)', () => {
88
+ const state: DashboardState = {
89
+ artifacts: new Map([
90
+ [
91
+ 'artifact-1',
92
+ {
93
+ artifact_id: 'artifact-1',
94
+ artifact_type: 'Movie',
95
+ produced_by: 'movie-agent',
96
+ consumed_by: ['tagline-agent'],
97
+ published_at: '2025-10-03T10:00:00Z',
98
+ payload: { title: 'Inception' },
99
+ correlation_id: 'corr-1',
100
+ },
101
+ ],
102
+ ]),
103
+ runs: new Map(),
104
+ };
105
+
106
+ expect(() => {
107
+ transforms.deriveAgentViewEdges(state);
108
+ }).toThrow('deriveAgentViewEdges not implemented');
109
+
110
+ // Expected behavior after implementation:
111
+ // const edges = transforms.deriveAgentViewEdges(state);
112
+ //
113
+ // expect(edges).toHaveLength(1);
114
+ // expect(edges[0].source).toBe('movie-agent');
115
+ // expect(edges[0].target).toBe('tagline-agent');
116
+ // expect(edges[0].type).toBe('message_flow');
117
+ });
118
+
119
+ it('should group edges by message_type', () => {
120
+ const state: DashboardState = {
121
+ artifacts: new Map([
122
+ [
123
+ 'artifact-1',
124
+ {
125
+ artifact_id: 'artifact-1',
126
+ artifact_type: 'Movie',
127
+ produced_by: 'movie-agent',
128
+ consumed_by: ['tagline-agent'],
129
+ published_at: '2025-10-03T10:00:00Z',
130
+ payload: {},
131
+ correlation_id: 'corr-1',
132
+ },
133
+ ],
134
+ [
135
+ 'artifact-2',
136
+ {
137
+ artifact_id: 'artifact-2',
138
+ artifact_type: 'Movie',
139
+ produced_by: 'movie-agent',
140
+ consumed_by: ['tagline-agent'],
141
+ published_at: '2025-10-03T10:01:00Z',
142
+ payload: {},
143
+ correlation_id: 'corr-1',
144
+ },
145
+ ],
146
+ [
147
+ 'artifact-3',
148
+ {
149
+ artifact_id: 'artifact-3',
150
+ artifact_type: 'Tagline',
151
+ produced_by: 'tagline-agent',
152
+ consumed_by: ['output-agent'],
153
+ published_at: '2025-10-03T10:02:00Z',
154
+ payload: {},
155
+ correlation_id: 'corr-1',
156
+ },
157
+ ],
158
+ ]),
159
+ runs: new Map(),
160
+ };
161
+
162
+ expect(() => {
163
+ transforms.deriveAgentViewEdges(state);
164
+ }).toThrow('deriveAgentViewEdges not implemented');
165
+
166
+ // Expected behavior:
167
+ // const edges = transforms.deriveAgentViewEdges(state);
168
+ //
169
+ // // Should have 2 edges: movie→tagline (Movie type), tagline→output (Tagline type)
170
+ // expect(edges).toHaveLength(2);
171
+ //
172
+ // const movieEdge = edges.find(e => e.data.message_type === 'Movie');
173
+ // expect(movieEdge).toBeDefined();
174
+ // expect(movieEdge!.source).toBe('movie-agent');
175
+ // expect(movieEdge!.target).toBe('tagline-agent');
176
+ //
177
+ // const taglineEdge = edges.find(e => e.data.message_type === 'Tagline');
178
+ // expect(taglineEdge).toBeDefined();
179
+ // expect(taglineEdge!.source).toBe('tagline-agent');
180
+ // expect(taglineEdge!.target).toBe('output-agent');
181
+ });
182
+
183
+ it('should count artifacts per edge', () => {
184
+ const state: DashboardState = {
185
+ artifacts: new Map([
186
+ [
187
+ 'artifact-1',
188
+ {
189
+ artifact_id: 'artifact-1',
190
+ artifact_type: 'Movie',
191
+ produced_by: 'movie-agent',
192
+ consumed_by: ['tagline-agent'],
193
+ published_at: '2025-10-03T10:00:00Z',
194
+ payload: {},
195
+ correlation_id: 'corr-1',
196
+ },
197
+ ],
198
+ [
199
+ 'artifact-2',
200
+ {
201
+ artifact_id: 'artifact-2',
202
+ artifact_type: 'Movie',
203
+ produced_by: 'movie-agent',
204
+ consumed_by: ['tagline-agent'],
205
+ published_at: '2025-10-03T10:01:00Z',
206
+ payload: {},
207
+ correlation_id: 'corr-2',
208
+ },
209
+ ],
210
+ [
211
+ 'artifact-3',
212
+ {
213
+ artifact_id: 'artifact-3',
214
+ artifact_type: 'Movie',
215
+ produced_by: 'movie-agent',
216
+ consumed_by: ['tagline-agent'],
217
+ published_at: '2025-10-03T10:02:00Z',
218
+ payload: {},
219
+ correlation_id: 'corr-3',
220
+ },
221
+ ],
222
+ ]),
223
+ runs: new Map(),
224
+ };
225
+
226
+ expect(() => {
227
+ transforms.deriveAgentViewEdges(state);
228
+ }).toThrow('deriveAgentViewEdges not implemented');
229
+
230
+ // Expected behavior:
231
+ // const edges = transforms.deriveAgentViewEdges(state);
232
+ //
233
+ // expect(edges).toHaveLength(1);
234
+ // expect(edges[0].data.message_count).toBe(3);
235
+ // expect(edges[0].data.artifact_ids).toHaveLength(3);
236
+ // expect(edges[0].data.artifact_ids).toContain('artifact-1');
237
+ // expect(edges[0].data.artifact_ids).toContain('artifact-2');
238
+ // expect(edges[0].data.artifact_ids).toContain('artifact-3');
239
+ });
240
+
241
+ it('should format edge label as "Type (N)"', () => {
242
+ const state: DashboardState = {
243
+ artifacts: new Map([
244
+ [
245
+ 'artifact-1',
246
+ {
247
+ artifact_id: 'artifact-1',
248
+ artifact_type: 'Movie',
249
+ produced_by: 'movie-agent',
250
+ consumed_by: ['tagline-agent'],
251
+ published_at: '2025-10-03T10:00:00Z',
252
+ payload: {},
253
+ correlation_id: 'corr-1',
254
+ },
255
+ ],
256
+ [
257
+ 'artifact-2',
258
+ {
259
+ artifact_id: 'artifact-2',
260
+ artifact_type: 'Movie',
261
+ produced_by: 'movie-agent',
262
+ consumed_by: ['tagline-agent'],
263
+ published_at: '2025-10-03T10:01:00Z',
264
+ payload: {},
265
+ correlation_id: 'corr-2',
266
+ },
267
+ ],
268
+ ]),
269
+ runs: new Map(),
270
+ };
271
+
272
+ expect(() => {
273
+ transforms.deriveAgentViewEdges(state);
274
+ }).toThrow('deriveAgentViewEdges not implemented');
275
+
276
+ // Expected behavior:
277
+ // const edges = transforms.deriveAgentViewEdges(state);
278
+ //
279
+ // expect(edges).toHaveLength(1);
280
+ // expect(edges[0].label).toBe('Movie (2)');
281
+ });
282
+
283
+ it('should track latest_timestamp for each edge', () => {
284
+ const state: DashboardState = {
285
+ artifacts: new Map([
286
+ [
287
+ 'artifact-1',
288
+ {
289
+ artifact_id: 'artifact-1',
290
+ artifact_type: 'Movie',
291
+ produced_by: 'movie-agent',
292
+ consumed_by: ['tagline-agent'],
293
+ published_at: '2025-10-03T10:00:00Z',
294
+ payload: {},
295
+ correlation_id: 'corr-1',
296
+ },
297
+ ],
298
+ [
299
+ 'artifact-2',
300
+ {
301
+ artifact_id: 'artifact-2',
302
+ artifact_type: 'Movie',
303
+ produced_by: 'movie-agent',
304
+ consumed_by: ['tagline-agent'],
305
+ published_at: '2025-10-03T10:05:00Z', // Latest
306
+ payload: {},
307
+ correlation_id: 'corr-2',
308
+ },
309
+ ],
310
+ [
311
+ 'artifact-3',
312
+ {
313
+ artifact_id: 'artifact-3',
314
+ artifact_type: 'Movie',
315
+ produced_by: 'movie-agent',
316
+ consumed_by: ['tagline-agent'],
317
+ published_at: '2025-10-03T10:02:00Z',
318
+ payload: {},
319
+ correlation_id: 'corr-3',
320
+ },
321
+ ],
322
+ ]),
323
+ runs: new Map(),
324
+ };
325
+
326
+ expect(() => {
327
+ transforms.deriveAgentViewEdges(state);
328
+ }).toThrow('deriveAgentViewEdges not implemented');
329
+
330
+ // Expected behavior:
331
+ // const edges = transforms.deriveAgentViewEdges(state);
332
+ //
333
+ // expect(edges).toHaveLength(1);
334
+ // expect(edges[0].data.latest_timestamp).toBe('2025-10-03T10:05:00Z');
335
+ });
336
+
337
+ it('should create unique edge IDs using edgeKey format', () => {
338
+ const state: DashboardState = {
339
+ artifacts: new Map([
340
+ [
341
+ 'artifact-1',
342
+ {
343
+ artifact_id: 'artifact-1',
344
+ artifact_type: 'Movie',
345
+ produced_by: 'movie-agent',
346
+ consumed_by: ['tagline-agent'],
347
+ published_at: '2025-10-03T10:00:00Z',
348
+ payload: {},
349
+ correlation_id: 'corr-1',
350
+ },
351
+ ],
352
+ ]),
353
+ runs: new Map(),
354
+ };
355
+
356
+ expect(() => {
357
+ transforms.deriveAgentViewEdges(state);
358
+ }).toThrow('deriveAgentViewEdges not implemented');
359
+
360
+ // Expected behavior (from DATA_MODEL.md line 782):
361
+ // const edges = transforms.deriveAgentViewEdges(state);
362
+ //
363
+ // expect(edges).toHaveLength(1);
364
+ // // Edge ID format: `${source}_${target}_${message_type}`
365
+ // expect(edges[0].id).toBe('movie-agent_tagline-agent_Movie');
366
+ });
367
+
368
+ it('should handle multiple consumers (fan-out)', () => {
369
+ const state: DashboardState = {
370
+ artifacts: new Map([
371
+ [
372
+ 'artifact-1',
373
+ {
374
+ artifact_id: 'artifact-1',
375
+ artifact_type: 'Movie',
376
+ produced_by: 'movie-agent',
377
+ consumed_by: ['tagline-agent', 'summary-agent', 'rating-agent'],
378
+ published_at: '2025-10-03T10:00:00Z',
379
+ payload: {},
380
+ correlation_id: 'corr-1',
381
+ },
382
+ ],
383
+ ]),
384
+ runs: new Map(),
385
+ };
386
+
387
+ expect(() => {
388
+ transforms.deriveAgentViewEdges(state);
389
+ }).toThrow('deriveAgentViewEdges not implemented');
390
+
391
+ // Expected behavior:
392
+ // const edges = transforms.deriveAgentViewEdges(state);
393
+ //
394
+ // // Should create 3 edges: movie→tagline, movie→summary, movie→rating
395
+ // expect(edges).toHaveLength(3);
396
+ //
397
+ // const targets = edges.map(e => e.target).sort();
398
+ // expect(targets).toEqual(['rating-agent', 'summary-agent', 'tagline-agent']);
399
+ //
400
+ // // All should have the same source
401
+ // edges.forEach(edge => {
402
+ // expect(edge.source).toBe('movie-agent');
403
+ // });
404
+ });
405
+
406
+ it('should handle empty consumed_by array (no edges)', () => {
407
+ const state: DashboardState = {
408
+ artifacts: new Map([
409
+ [
410
+ 'artifact-1',
411
+ {
412
+ artifact_id: 'artifact-1',
413
+ artifact_type: 'Movie',
414
+ produced_by: 'movie-agent',
415
+ consumed_by: [], // No consumers
416
+ published_at: '2025-10-03T10:00:00Z',
417
+ payload: {},
418
+ correlation_id: 'corr-1',
419
+ },
420
+ ],
421
+ ]),
422
+ runs: new Map(),
423
+ };
424
+
425
+ expect(() => {
426
+ transforms.deriveAgentViewEdges(state);
427
+ }).toThrow('deriveAgentViewEdges not implemented');
428
+
429
+ // Expected behavior:
430
+ // const edges = transforms.deriveAgentViewEdges(state);
431
+ //
432
+ // // No edges should be created
433
+ // expect(edges).toHaveLength(0);
434
+ });
435
+
436
+ it('should return empty array for empty state', () => {
437
+ const state: DashboardState = {
438
+ artifacts: new Map(),
439
+ runs: new Map(),
440
+ };
441
+
442
+ expect(() => {
443
+ transforms.deriveAgentViewEdges(state);
444
+ }).toThrow('deriveAgentViewEdges not implemented');
445
+
446
+ // Expected behavior:
447
+ // const edges = transforms.deriveAgentViewEdges(state);
448
+ // expect(edges).toHaveLength(0);
449
+ // expect(edges).toEqual([]);
450
+ });
451
+ });
452
+
453
+ describe('deriveBlackboardViewEdges - Transformation Edges', () => {
454
+ it('should create edges between artifacts (consumed → produced)', () => {
455
+ const state: DashboardState = {
456
+ artifacts: new Map([
457
+ ['artifact-1', { artifact_id: 'artifact-1' } as Artifact],
458
+ ['artifact-2', { artifact_id: 'artifact-2' } as Artifact],
459
+ ]),
460
+ runs: new Map([
461
+ [
462
+ 'run-1',
463
+ {
464
+ run_id: 'run-1',
465
+ correlation_id: 'test-correlation',
466
+ agent_name: 'tagline-agent',
467
+ status: 'completed',
468
+ consumed_artifacts: ['artifact-1'],
469
+ produced_artifacts: ['artifact-2'],
470
+ duration_ms: 1500,
471
+ },
472
+ ],
473
+ ]),
474
+ };
475
+
476
+ expect(() => {
477
+ transforms.deriveBlackboardViewEdges(state);
478
+ }).toThrow('deriveBlackboardViewEdges not implemented');
479
+
480
+ // Expected behavior:
481
+ // const edges = transforms.deriveBlackboardViewEdges(state);
482
+ //
483
+ // expect(edges).toHaveLength(1);
484
+ // expect(edges[0].source).toBe('artifact-1');
485
+ // expect(edges[0].target).toBe('artifact-2');
486
+ // expect(edges[0].type).toBe('transformation');
487
+ });
488
+
489
+ it('should create one edge per consumed × produced pair', () => {
490
+ const state: DashboardState = {
491
+ artifacts: new Map([
492
+ ['artifact-1', { artifact_id: 'artifact-1' } as Artifact],
493
+ ['artifact-2', { artifact_id: 'artifact-2' } as Artifact],
494
+ ['artifact-3', { artifact_id: 'artifact-3' } as Artifact],
495
+ ]),
496
+ runs: new Map([
497
+ [
498
+ 'run-1',
499
+ {
500
+ run_id: 'run-1',
501
+ correlation_id: 'test-correlation',
502
+ agent_name: 'multi-agent',
503
+ status: 'completed',
504
+ consumed_artifacts: ['artifact-1', 'artifact-2'],
505
+ produced_artifacts: ['artifact-3'],
506
+ duration_ms: 2000,
507
+ },
508
+ ],
509
+ ]),
510
+ };
511
+
512
+ expect(() => {
513
+ transforms.deriveBlackboardViewEdges(state);
514
+ }).toThrow('deriveBlackboardViewEdges not implemented');
515
+
516
+ // Expected behavior:
517
+ // const edges = transforms.deriveBlackboardViewEdges(state);
518
+ //
519
+ // // Should create 2 edges: artifact-1→artifact-3, artifact-2→artifact-3
520
+ // expect(edges).toHaveLength(2);
521
+ //
522
+ // const edge1 = edges.find(e => e.source === 'artifact-1');
523
+ // expect(edge1).toBeDefined();
524
+ // expect(edge1!.target).toBe('artifact-3');
525
+ //
526
+ // const edge2 = edges.find(e => e.source === 'artifact-2');
527
+ // expect(edge2).toBeDefined();
528
+ // expect(edge2!.target).toBe('artifact-3');
529
+ });
530
+
531
+ it('should label edges with agent_name', () => {
532
+ const state: DashboardState = {
533
+ artifacts: new Map([
534
+ ['artifact-1', { artifact_id: 'artifact-1' } as Artifact],
535
+ ['artifact-2', { artifact_id: 'artifact-2' } as Artifact],
536
+ ]),
537
+ runs: new Map([
538
+ [
539
+ 'run-1',
540
+ {
541
+ run_id: 'run-1',
542
+ correlation_id: 'test-correlation',
543
+ agent_name: 'tagline-agent',
544
+ status: 'completed',
545
+ consumed_artifacts: ['artifact-1'],
546
+ produced_artifacts: ['artifact-2'],
547
+ duration_ms: 1500,
548
+ },
549
+ ],
550
+ ]),
551
+ };
552
+
553
+ expect(() => {
554
+ transforms.deriveBlackboardViewEdges(state);
555
+ }).toThrow('deriveBlackboardViewEdges not implemented');
556
+
557
+ // Expected behavior (from DATA_MODEL.md line 841):
558
+ // const edges = transforms.deriveBlackboardViewEdges(state);
559
+ //
560
+ // expect(edges).toHaveLength(1);
561
+ // expect(edges[0].label).toBe('tagline-agent');
562
+ });
563
+
564
+ it('should include edge data with run metadata', () => {
565
+ const state: DashboardState = {
566
+ artifacts: new Map([
567
+ ['artifact-1', { artifact_id: 'artifact-1' } as Artifact],
568
+ ['artifact-2', { artifact_id: 'artifact-2' } as Artifact],
569
+ ]),
570
+ runs: new Map([
571
+ [
572
+ 'run-1',
573
+ {
574
+ run_id: 'run-1',
575
+ correlation_id: 'test-correlation',
576
+ agent_name: 'tagline-agent',
577
+ status: 'completed',
578
+ consumed_artifacts: ['artifact-1'],
579
+ produced_artifacts: ['artifact-2'],
580
+ duration_ms: 1500,
581
+ },
582
+ ],
583
+ ]),
584
+ };
585
+
586
+ expect(() => {
587
+ transforms.deriveBlackboardViewEdges(state);
588
+ }).toThrow('deriveBlackboardViewEdges not implemented');
589
+
590
+ // Expected behavior (from DATA_MODEL.md lines 842-846):
591
+ // const edges = transforms.deriveBlackboardViewEdges(state);
592
+ //
593
+ // expect(edges).toHaveLength(1);
594
+ // expect(edges[0].data).toEqual({
595
+ // transformer_agent: 'tagline-agent',
596
+ // run_id: 'run-1',
597
+ // correlation_id: 'test-correlation',
598
+ // duration_ms: 1500,
599
+ // });
600
+ });
601
+
602
+ it('should skip active runs (status === "active")', () => {
603
+ const state: DashboardState = {
604
+ artifacts: new Map([
605
+ ['artifact-1', { artifact_id: 'artifact-1' } as Artifact],
606
+ ['artifact-2', { artifact_id: 'artifact-2' } as Artifact],
607
+ ]),
608
+ runs: new Map([
609
+ [
610
+ 'run-1',
611
+ {
612
+ run_id: 'run-1',
613
+ correlation_id: 'test-correlation',
614
+ agent_name: 'active-agent',
615
+ status: 'active', // Still running
616
+ consumed_artifacts: ['artifact-1'],
617
+ produced_artifacts: ['artifact-2'],
618
+ },
619
+ ],
620
+ [
621
+ 'run-2',
622
+ {
623
+ run_id: 'run-2',
624
+ correlation_id: 'test-correlation',
625
+ agent_name: 'completed-agent',
626
+ status: 'completed',
627
+ consumed_artifacts: ['artifact-1'],
628
+ produced_artifacts: ['artifact-2'],
629
+ duration_ms: 1000,
630
+ },
631
+ ],
632
+ ]),
633
+ };
634
+
635
+ expect(() => {
636
+ transforms.deriveBlackboardViewEdges(state);
637
+ }).toThrow('deriveBlackboardViewEdges not implemented');
638
+
639
+ // Expected behavior (from DATA_MODEL.md line 831):
640
+ // const edges = transforms.deriveBlackboardViewEdges(state);
641
+ //
642
+ // // Only run-2 should create an edge (run-1 is active)
643
+ // expect(edges).toHaveLength(1);
644
+ // expect(edges[0].data.run_id).toBe('run-2');
645
+ });
646
+
647
+ it('should generate unique edge IDs', () => {
648
+ const state: DashboardState = {
649
+ artifacts: new Map([
650
+ ['artifact-1', { artifact_id: 'artifact-1' } as Artifact],
651
+ ['artifact-2', { artifact_id: 'artifact-2' } as Artifact],
652
+ ]),
653
+ runs: new Map([
654
+ [
655
+ 'run-1',
656
+ {
657
+ run_id: 'run-1',
658
+ correlation_id: 'test-correlation',
659
+ agent_name: 'agent-1',
660
+ status: 'completed',
661
+ consumed_artifacts: ['artifact-1'],
662
+ produced_artifacts: ['artifact-2'],
663
+ duration_ms: 1000,
664
+ },
665
+ ],
666
+ ]),
667
+ };
668
+
669
+ expect(() => {
670
+ transforms.deriveBlackboardViewEdges(state);
671
+ }).toThrow('deriveBlackboardViewEdges not implemented');
672
+
673
+ // Expected behavior (from DATA_MODEL.md line 837):
674
+ // const edges = transforms.deriveBlackboardViewEdges(state);
675
+ //
676
+ // expect(edges).toHaveLength(1);
677
+ // // Edge ID format: `${consumed_id}_${produced_id}`
678
+ // expect(edges[0].id).toBe('artifact-1_artifact-2');
679
+ });
680
+
681
+ it('should handle runs with no consumed artifacts', () => {
682
+ const state: DashboardState = {
683
+ artifacts: new Map([
684
+ ['artifact-1', { artifact_id: 'artifact-1' } as Artifact],
685
+ ]),
686
+ runs: new Map([
687
+ [
688
+ 'run-1',
689
+ {
690
+ run_id: 'run-1',
691
+ correlation_id: 'test-correlation',
692
+ agent_name: 'source-agent',
693
+ status: 'completed',
694
+ consumed_artifacts: [], // No inputs
695
+ produced_artifacts: ['artifact-1'],
696
+ duration_ms: 500,
697
+ },
698
+ ],
699
+ ]),
700
+ };
701
+
702
+ expect(() => {
703
+ transforms.deriveBlackboardViewEdges(state);
704
+ }).toThrow('deriveBlackboardViewEdges not implemented');
705
+
706
+ // Expected behavior:
707
+ // const edges = transforms.deriveBlackboardViewEdges(state);
708
+ //
709
+ // // No edges should be created (no consumed artifacts)
710
+ // expect(edges).toHaveLength(0);
711
+ });
712
+
713
+ it('should handle runs with no produced artifacts', () => {
714
+ const state: DashboardState = {
715
+ artifacts: new Map([
716
+ ['artifact-1', { artifact_id: 'artifact-1' } as Artifact],
717
+ ]),
718
+ runs: new Map([
719
+ [
720
+ 'run-1',
721
+ {
722
+ run_id: 'run-1',
723
+ correlation_id: 'test-correlation',
724
+ agent_name: 'sink-agent',
725
+ status: 'completed',
726
+ consumed_artifacts: ['artifact-1'],
727
+ produced_artifacts: [], // No outputs
728
+ duration_ms: 500,
729
+ },
730
+ ],
731
+ ]),
732
+ };
733
+
734
+ expect(() => {
735
+ transforms.deriveBlackboardViewEdges(state);
736
+ }).toThrow('deriveBlackboardViewEdges not implemented');
737
+
738
+ // Expected behavior:
739
+ // const edges = transforms.deriveBlackboardViewEdges(state);
740
+ //
741
+ // // No edges should be created (no produced artifacts)
742
+ // expect(edges).toHaveLength(0);
743
+ });
744
+
745
+ it('should return empty array for empty runs', () => {
746
+ const state: DashboardState = {
747
+ artifacts: new Map(),
748
+ runs: new Map(),
749
+ };
750
+
751
+ expect(() => {
752
+ transforms.deriveBlackboardViewEdges(state);
753
+ }).toThrow('deriveBlackboardViewEdges not implemented');
754
+
755
+ // Expected behavior:
756
+ // const edges = transforms.deriveBlackboardViewEdges(state);
757
+ // expect(edges).toHaveLength(0);
758
+ // expect(edges).toEqual([]);
759
+ });
760
+ });
761
+
762
+ describe('Edge Deduplication', () => {
763
+ it('should not duplicate Agent View edges with same source, target, and type', () => {
764
+ const state: DashboardState = {
765
+ artifacts: new Map([
766
+ [
767
+ 'artifact-1',
768
+ {
769
+ artifact_id: 'artifact-1',
770
+ artifact_type: 'Movie',
771
+ produced_by: 'movie-agent',
772
+ consumed_by: ['tagline-agent'],
773
+ published_at: '2025-10-03T10:00:00Z',
774
+ payload: {},
775
+ correlation_id: 'corr-1',
776
+ },
777
+ ],
778
+ [
779
+ 'artifact-2',
780
+ {
781
+ artifact_id: 'artifact-2',
782
+ artifact_type: 'Movie',
783
+ produced_by: 'movie-agent',
784
+ consumed_by: ['tagline-agent'],
785
+ published_at: '2025-10-03T10:01:00Z',
786
+ payload: {},
787
+ correlation_id: 'corr-2',
788
+ },
789
+ ],
790
+ ]),
791
+ runs: new Map(),
792
+ };
793
+
794
+ expect(() => {
795
+ transforms.deriveAgentViewEdges(state);
796
+ }).toThrow('deriveAgentViewEdges not implemented');
797
+
798
+ // Expected behavior:
799
+ // const edges = transforms.deriveAgentViewEdges(state);
800
+ //
801
+ // // Should create only 1 edge (not 2) with count of 2
802
+ // expect(edges).toHaveLength(1);
803
+ // expect(edges[0].data.message_count).toBe(2);
804
+ });
805
+
806
+ it('should allow multiple Blackboard View edges with same source and target from different runs', () => {
807
+ const state: DashboardState = {
808
+ artifacts: new Map([
809
+ ['artifact-1', { artifact_id: 'artifact-1' } as Artifact],
810
+ ['artifact-2', { artifact_id: 'artifact-2' } as Artifact],
811
+ ]),
812
+ runs: new Map([
813
+ [
814
+ 'run-1',
815
+ {
816
+ run_id: 'run-1',
817
+ correlation_id: 'test-correlation',
818
+ agent_name: 'agent-1',
819
+ status: 'completed',
820
+ consumed_artifacts: ['artifact-1'],
821
+ produced_artifacts: ['artifact-2'],
822
+ duration_ms: 1000,
823
+ },
824
+ ],
825
+ [
826
+ 'run-2',
827
+ {
828
+ run_id: 'run-2',
829
+ correlation_id: 'test-correlation',
830
+ agent_name: 'agent-2',
831
+ status: 'completed',
832
+ consumed_artifacts: ['artifact-1'],
833
+ produced_artifacts: ['artifact-2'],
834
+ duration_ms: 1500,
835
+ },
836
+ ],
837
+ ]),
838
+ };
839
+
840
+ expect(() => {
841
+ transforms.deriveBlackboardViewEdges(state);
842
+ }).toThrow('deriveBlackboardViewEdges not implemented');
843
+
844
+ // Expected behavior:
845
+ // const edges = transforms.deriveBlackboardViewEdges(state);
846
+ //
847
+ // // Should create 2 edges (same source/target but different runs)
848
+ // // This will cause overlapping edges, but that's expected per spec
849
+ // expect(edges).toHaveLength(2);
850
+ //
851
+ // const edge1 = edges.find(e => e.data.run_id === 'run-1');
852
+ // const edge2 = edges.find(e => e.data.run_id === 'run-2');
853
+ //
854
+ // expect(edge1).toBeDefined();
855
+ // expect(edge2).toBeDefined();
856
+ //
857
+ // // Note: React Flow will need to handle overlapping edges visually
858
+ });
859
+ });
860
+ });