flock-core 0.5.0b71__py3-none-any.whl → 0.5.1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of flock-core might be problematic. Click here for more details.

Files changed (65) hide show
  1. flock/agent.py +39 -1
  2. flock/artifacts.py +17 -10
  3. flock/cli.py +1 -1
  4. flock/dashboard/__init__.py +2 -0
  5. flock/dashboard/collector.py +282 -6
  6. flock/dashboard/events.py +6 -0
  7. flock/dashboard/graph_builder.py +563 -0
  8. flock/dashboard/launcher.py +11 -6
  9. flock/dashboard/models/__init__.py +1 -0
  10. flock/dashboard/models/graph.py +156 -0
  11. flock/dashboard/service.py +175 -14
  12. flock/dashboard/static_v2/assets/index-DFRnI_mt.js +111 -0
  13. flock/dashboard/static_v2/assets/index-fPLNdmp1.css +1 -0
  14. flock/dashboard/static_v2/index.html +13 -0
  15. flock/dashboard/websocket.py +2 -2
  16. flock/engines/dspy_engine.py +294 -20
  17. flock/frontend/README.md +6 -6
  18. flock/frontend/src/App.tsx +23 -31
  19. flock/frontend/src/__tests__/integration/graph-snapshot.test.tsx +647 -0
  20. flock/frontend/src/components/details/DetailWindowContainer.tsx +13 -17
  21. flock/frontend/src/components/details/MessageDetailWindow.tsx +439 -0
  22. flock/frontend/src/components/details/MessageHistoryTab.tsx +128 -53
  23. flock/frontend/src/components/details/RunStatusTab.tsx +79 -38
  24. flock/frontend/src/components/graph/AgentNode.test.tsx +3 -1
  25. flock/frontend/src/components/graph/AgentNode.tsx +8 -6
  26. flock/frontend/src/components/graph/GraphCanvas.tsx +13 -8
  27. flock/frontend/src/components/graph/MessageNode.test.tsx +3 -1
  28. flock/frontend/src/components/graph/MessageNode.tsx +16 -3
  29. flock/frontend/src/components/layout/DashboardLayout.tsx +12 -9
  30. flock/frontend/src/components/modules/HistoricalArtifactsModule.tsx +4 -14
  31. flock/frontend/src/components/modules/ModuleRegistry.ts +5 -3
  32. flock/frontend/src/hooks/useModules.ts +12 -4
  33. flock/frontend/src/hooks/usePersistence.ts +5 -3
  34. flock/frontend/src/services/api.ts +3 -19
  35. flock/frontend/src/services/graphService.test.ts +330 -0
  36. flock/frontend/src/services/graphService.ts +75 -0
  37. flock/frontend/src/services/websocket.ts +104 -268
  38. flock/frontend/src/store/filterStore.test.ts +89 -1
  39. flock/frontend/src/store/filterStore.ts +38 -16
  40. flock/frontend/src/store/graphStore.test.ts +538 -173
  41. flock/frontend/src/store/graphStore.ts +374 -465
  42. flock/frontend/src/store/moduleStore.ts +51 -33
  43. flock/frontend/src/store/uiStore.ts +23 -11
  44. flock/frontend/src/types/graph.ts +77 -44
  45. flock/frontend/src/utils/mockData.ts +16 -3
  46. flock/frontend/vite.config.ts +2 -2
  47. flock/orchestrator.py +27 -7
  48. flock/patches/__init__.py +5 -0
  49. flock/patches/dspy_streaming_patch.py +82 -0
  50. flock/service.py +2 -2
  51. flock/store.py +169 -4
  52. flock/themes/darkmatrix.toml +2 -2
  53. flock/themes/deep.toml +2 -2
  54. flock/themes/neopolitan.toml +4 -4
  55. {flock_core-0.5.0b71.dist-info → flock_core-0.5.1.dist-info}/METADATA +20 -13
  56. {flock_core-0.5.0b71.dist-info → flock_core-0.5.1.dist-info}/RECORD +59 -53
  57. flock/frontend/src/__tests__/e2e/critical-scenarios.test.tsx +0 -586
  58. flock/frontend/src/__tests__/integration/filtering-e2e.test.tsx +0 -391
  59. flock/frontend/src/__tests__/integration/graph-rendering.test.tsx +0 -640
  60. flock/frontend/src/services/websocket.test.ts +0 -595
  61. flock/frontend/src/utils/transforms.test.ts +0 -860
  62. flock/frontend/src/utils/transforms.ts +0 -323
  63. {flock_core-0.5.0b71.dist-info → flock_core-0.5.1.dist-info}/WHEEL +0 -0
  64. {flock_core-0.5.0b71.dist-info → flock_core-0.5.1.dist-info}/entry_points.txt +0 -0
  65. {flock_core-0.5.0b71.dist-info → flock_core-0.5.1.dist-info}/licenses/LICENSE +0 -0
@@ -0,0 +1 @@
1
+ .react-flow{direction:ltr;--xy-edge-stroke-default: #b1b1b7;--xy-edge-stroke-width-default: 1;--xy-edge-stroke-selected-default: #555;--xy-connectionline-stroke-default: #b1b1b7;--xy-connectionline-stroke-width-default: 1;--xy-attribution-background-color-default: rgba(255, 255, 255, .5);--xy-minimap-background-color-default: #fff;--xy-minimap-mask-background-color-default: rgba(240, 240, 240, .6);--xy-minimap-mask-stroke-color-default: transparent;--xy-minimap-mask-stroke-width-default: 1;--xy-minimap-node-background-color-default: #e2e2e2;--xy-minimap-node-stroke-color-default: transparent;--xy-minimap-node-stroke-width-default: 2;--xy-background-color-default: transparent;--xy-background-pattern-dots-color-default: #91919a;--xy-background-pattern-lines-color-default: #eee;--xy-background-pattern-cross-color-default: #e2e2e2;background-color:var(--xy-background-color, var(--xy-background-color-default));--xy-node-color-default: inherit;--xy-node-border-default: 1px solid #1a192b;--xy-node-background-color-default: #fff;--xy-node-group-background-color-default: rgba(240, 240, 240, .25);--xy-node-boxshadow-hover-default: 0 1px 4px 1px rgba(0, 0, 0, .08);--xy-node-boxshadow-selected-default: 0 0 0 .5px #1a192b;--xy-node-border-radius-default: 3px;--xy-handle-background-color-default: #1a192b;--xy-handle-border-color-default: #fff;--xy-selection-background-color-default: rgba(0, 89, 220, .08);--xy-selection-border-default: 1px dotted rgba(0, 89, 220, .8);--xy-controls-button-background-color-default: #fefefe;--xy-controls-button-background-color-hover-default: #f4f4f4;--xy-controls-button-color-default: inherit;--xy-controls-button-color-hover-default: inherit;--xy-controls-button-border-color-default: #eee;--xy-controls-box-shadow-default: 0 0 2px 1px rgba(0, 0, 0, .08);--xy-edge-label-background-color-default: #ffffff;--xy-edge-label-color-default: inherit;--xy-resize-background-color-default: #3367d9}.react-flow.dark{--xy-edge-stroke-default: #3e3e3e;--xy-edge-stroke-width-default: 1;--xy-edge-stroke-selected-default: #727272;--xy-connectionline-stroke-default: #b1b1b7;--xy-connectionline-stroke-width-default: 1;--xy-attribution-background-color-default: rgba(150, 150, 150, .25);--xy-minimap-background-color-default: #141414;--xy-minimap-mask-background-color-default: rgba(60, 60, 60, .6);--xy-minimap-mask-stroke-color-default: transparent;--xy-minimap-mask-stroke-width-default: 1;--xy-minimap-node-background-color-default: #2b2b2b;--xy-minimap-node-stroke-color-default: transparent;--xy-minimap-node-stroke-width-default: 2;--xy-background-color-default: #141414;--xy-background-pattern-dots-color-default: #777;--xy-background-pattern-lines-color-default: #777;--xy-background-pattern-cross-color-default: #777;--xy-node-color-default: #f8f8f8;--xy-node-border-default: 1px solid #3c3c3c;--xy-node-background-color-default: #1e1e1e;--xy-node-group-background-color-default: rgba(240, 240, 240, .25);--xy-node-boxshadow-hover-default: 0 1px 4px 1px rgba(255, 255, 255, .08);--xy-node-boxshadow-selected-default: 0 0 0 .5px #999;--xy-handle-background-color-default: #bebebe;--xy-handle-border-color-default: #1e1e1e;--xy-selection-background-color-default: rgba(200, 200, 220, .08);--xy-selection-border-default: 1px dotted rgba(200, 200, 220, .8);--xy-controls-button-background-color-default: #2b2b2b;--xy-controls-button-background-color-hover-default: #3e3e3e;--xy-controls-button-color-default: #f8f8f8;--xy-controls-button-color-hover-default: #fff;--xy-controls-button-border-color-default: #5b5b5b;--xy-controls-box-shadow-default: 0 0 2px 1px rgba(0, 0, 0, .08);--xy-edge-label-background-color-default: #141414;--xy-edge-label-color-default: #f8f8f8}.react-flow__background{background-color:var(--xy-background-color-props, var(--xy-background-color, var(--xy-background-color-default)));pointer-events:none;z-index:-1}.react-flow__container{position:absolute;width:100%;height:100%;top:0;left:0}.react-flow__pane{z-index:1}.react-flow__pane.draggable{cursor:grab}.react-flow__pane.dragging{cursor:grabbing}.react-flow__pane.selection{cursor:pointer}.react-flow__viewport{transform-origin:0 0;z-index:2;pointer-events:none}.react-flow__renderer{z-index:4}.react-flow__selection{z-index:6}.react-flow__nodesselection-rect:focus,.react-flow__nodesselection-rect:focus-visible{outline:none}.react-flow__edge-path{stroke:var(--xy-edge-stroke, var(--xy-edge-stroke-default));stroke-width:var(--xy-edge-stroke-width, var(--xy-edge-stroke-width-default));fill:none}.react-flow__connection-path{stroke:var(--xy-connectionline-stroke, var(--xy-connectionline-stroke-default));stroke-width:var(--xy-connectionline-stroke-width, var(--xy-connectionline-stroke-width-default));fill:none}.react-flow .react-flow__edges{position:absolute}.react-flow .react-flow__edges svg{overflow:visible;position:absolute;pointer-events:none}.react-flow__edge{pointer-events:visibleStroke}.react-flow__edge.selectable{cursor:pointer}.react-flow__edge.animated path{stroke-dasharray:5;animation:dashdraw .5s linear infinite}.react-flow__edge.animated path.react-flow__edge-interaction{stroke-dasharray:none;animation:none}.react-flow__edge.inactive{pointer-events:none}.react-flow__edge.selected,.react-flow__edge:focus,.react-flow__edge:focus-visible{outline:none}.react-flow__edge.selected .react-flow__edge-path,.react-flow__edge.selectable:focus .react-flow__edge-path,.react-flow__edge.selectable:focus-visible .react-flow__edge-path{stroke:var(--xy-edge-stroke-selected, var(--xy-edge-stroke-selected-default))}.react-flow__edge-textwrapper{pointer-events:all}.react-flow__edge .react-flow__edge-text{pointer-events:none;-webkit-user-select:none;-moz-user-select:none;user-select:none}.react-flow__arrowhead polyline{stroke:var(--xy-edge-stroke, var(--xy-edge-stroke-default))}.react-flow__arrowhead polyline.arrowclosed{fill:var(--xy-edge-stroke, var(--xy-edge-stroke-default))}.react-flow__connection{pointer-events:none}.react-flow__connection .animated{stroke-dasharray:5;animation:dashdraw .5s linear infinite}svg.react-flow__connectionline{z-index:1001;overflow:visible;position:absolute}.react-flow__nodes{pointer-events:none;transform-origin:0 0}.react-flow__node{position:absolute;-webkit-user-select:none;-moz-user-select:none;user-select:none;pointer-events:all;transform-origin:0 0;box-sizing:border-box;cursor:default}.react-flow__node.selectable{cursor:pointer}.react-flow__node.draggable{cursor:grab;pointer-events:all}.react-flow__node.draggable.dragging{cursor:grabbing}.react-flow__nodesselection{z-index:3;transform-origin:left top;pointer-events:none}.react-flow__nodesselection-rect{position:absolute;pointer-events:all;cursor:grab}.react-flow__handle{position:absolute;pointer-events:none;min-width:5px;min-height:5px;width:6px;height:6px;background-color:var(--xy-handle-background-color, var(--xy-handle-background-color-default));border:1px solid var(--xy-handle-border-color, var(--xy-handle-border-color-default));border-radius:100%}.react-flow__handle.connectingfrom{pointer-events:all}.react-flow__handle.connectionindicator{pointer-events:all;cursor:crosshair}.react-flow__handle-bottom{top:auto;left:50%;bottom:0;transform:translate(-50%,50%)}.react-flow__handle-top{top:0;left:50%;transform:translate(-50%,-50%)}.react-flow__handle-left{top:50%;left:0;transform:translate(-50%,-50%)}.react-flow__handle-right{top:50%;right:0;transform:translate(50%,-50%)}.react-flow__edgeupdater{cursor:move;pointer-events:all}.react-flow__pane.selection .react-flow__panel{pointer-events:none}.react-flow__panel{position:absolute;z-index:5;margin:15px}.react-flow__panel.top{top:0}.react-flow__panel.bottom{bottom:0}.react-flow__panel.top.center,.react-flow__panel.bottom.center{left:50%;transform:translate(-15px) translate(-50%)}.react-flow__panel.left{left:0}.react-flow__panel.right{right:0}.react-flow__panel.left.center,.react-flow__panel.right.center{top:50%;transform:translateY(-15px) translateY(-50%)}.react-flow__attribution{font-size:10px;background:var(--xy-attribution-background-color, var(--xy-attribution-background-color-default));padding:2px 3px;margin:0}.react-flow__attribution a{text-decoration:none;color:#999}@keyframes dashdraw{0%{stroke-dashoffset:10}}.react-flow__edgelabel-renderer{position:absolute;width:100%;height:100%;pointer-events:none;-webkit-user-select:none;-moz-user-select:none;user-select:none;left:0;top:0}.react-flow__viewport-portal{position:absolute;width:100%;height:100%;left:0;top:0;-webkit-user-select:none;-moz-user-select:none;user-select:none}.react-flow__minimap{background:var( --xy-minimap-background-color-props, var(--xy-minimap-background-color, var(--xy-minimap-background-color-default)) )}.react-flow__minimap-svg{display:block}.react-flow__minimap-mask{fill:var( --xy-minimap-mask-background-color-props, var(--xy-minimap-mask-background-color, var(--xy-minimap-mask-background-color-default)) );stroke:var( --xy-minimap-mask-stroke-color-props, var(--xy-minimap-mask-stroke-color, var(--xy-minimap-mask-stroke-color-default)) );stroke-width:var( --xy-minimap-mask-stroke-width-props, var(--xy-minimap-mask-stroke-width, var(--xy-minimap-mask-stroke-width-default)) )}.react-flow__minimap-node{fill:var( --xy-minimap-node-background-color-props, var(--xy-minimap-node-background-color, var(--xy-minimap-node-background-color-default)) );stroke:var( --xy-minimap-node-stroke-color-props, var(--xy-minimap-node-stroke-color, var(--xy-minimap-node-stroke-color-default)) );stroke-width:var( --xy-minimap-node-stroke-width-props, var(--xy-minimap-node-stroke-width, var(--xy-minimap-node-stroke-width-default)) )}.react-flow__background-pattern.dots{fill:var( --xy-background-pattern-color-props, var(--xy-background-pattern-color, var(--xy-background-pattern-dots-color-default)) )}.react-flow__background-pattern.lines{stroke:var( --xy-background-pattern-color-props, var(--xy-background-pattern-color, var(--xy-background-pattern-lines-color-default)) )}.react-flow__background-pattern.cross{stroke:var( --xy-background-pattern-color-props, var(--xy-background-pattern-color, var(--xy-background-pattern-cross-color-default)) )}.react-flow__controls{display:flex;flex-direction:column;box-shadow:var(--xy-controls-box-shadow, var(--xy-controls-box-shadow-default))}.react-flow__controls.horizontal{flex-direction:row}.react-flow__controls-button{display:flex;justify-content:center;align-items:center;height:26px;width:26px;padding:4px;border:none;background:var(--xy-controls-button-background-color, var(--xy-controls-button-background-color-default));border-bottom:1px solid var( --xy-controls-button-border-color-props, var(--xy-controls-button-border-color, var(--xy-controls-button-border-color-default)) );color:var( --xy-controls-button-color-props, var(--xy-controls-button-color, var(--xy-controls-button-color-default)) );cursor:pointer;-webkit-user-select:none;-moz-user-select:none;user-select:none}.react-flow__controls-button svg{width:100%;max-width:12px;max-height:12px;fill:currentColor}.react-flow__edge.updating .react-flow__edge-path{stroke:#777}.react-flow__edge-text{font-size:10px}.react-flow__node.selectable:focus,.react-flow__node.selectable:focus-visible{outline:none}.react-flow__node-input,.react-flow__node-default,.react-flow__node-output,.react-flow__node-group{padding:10px;border-radius:var(--xy-node-border-radius, var(--xy-node-border-radius-default));width:150px;font-size:12px;color:var(--xy-node-color, var(--xy-node-color-default));text-align:center;border:var(--xy-node-border, var(--xy-node-border-default));background-color:var(--xy-node-background-color, var(--xy-node-background-color-default))}.react-flow__node-input.selectable:hover,.react-flow__node-default.selectable:hover,.react-flow__node-output.selectable:hover,.react-flow__node-group.selectable:hover{box-shadow:var(--xy-node-boxshadow-hover, var(--xy-node-boxshadow-hover-default))}.react-flow__node-input.selectable.selected,.react-flow__node-input.selectable:focus,.react-flow__node-input.selectable:focus-visible,.react-flow__node-default.selectable.selected,.react-flow__node-default.selectable:focus,.react-flow__node-default.selectable:focus-visible,.react-flow__node-output.selectable.selected,.react-flow__node-output.selectable:focus,.react-flow__node-output.selectable:focus-visible,.react-flow__node-group.selectable.selected,.react-flow__node-group.selectable:focus,.react-flow__node-group.selectable:focus-visible{box-shadow:var(--xy-node-boxshadow-selected, var(--xy-node-boxshadow-selected-default))}.react-flow__node-group{background-color:var(--xy-node-group-background-color, var(--xy-node-group-background-color-default))}.react-flow__nodesselection-rect,.react-flow__selection{background:var(--xy-selection-background-color, var(--xy-selection-background-color-default));border:var(--xy-selection-border, var(--xy-selection-border-default))}.react-flow__nodesselection-rect:focus,.react-flow__nodesselection-rect:focus-visible,.react-flow__selection:focus,.react-flow__selection:focus-visible{outline:none}.react-flow__controls-button:hover{background:var( --xy-controls-button-background-color-hover-props, var(--xy-controls-button-background-color-hover, var(--xy-controls-button-background-color-hover-default)) );color:var( --xy-controls-button-color-hover-props, var(--xy-controls-button-color-hover, var(--xy-controls-button-color-hover-default)) )}.react-flow__controls-button:disabled{pointer-events:none}.react-flow__controls-button:disabled svg{fill-opacity:.4}.react-flow__controls-button:last-child{border-bottom:none}.react-flow__controls.horizontal .react-flow__controls-button{border-bottom:none;border-right:1px solid var( --xy-controls-button-border-color-props, var(--xy-controls-button-border-color, var(--xy-controls-button-border-color-default)) )}.react-flow__controls.horizontal .react-flow__controls-button:last-child{border-right:none}.react-flow__resize-control{position:absolute}.react-flow__resize-control.left,.react-flow__resize-control.right{cursor:ew-resize}.react-flow__resize-control.top,.react-flow__resize-control.bottom{cursor:ns-resize}.react-flow__resize-control.top.left,.react-flow__resize-control.bottom.right{cursor:nwse-resize}.react-flow__resize-control.bottom.left,.react-flow__resize-control.top.right{cursor:nesw-resize}.react-flow__resize-control.handle{width:5px;height:5px;border:1px solid #fff;border-radius:1px;background-color:var(--xy-resize-background-color, var(--xy-resize-background-color-default));translate:-50% -50%}.react-flow__resize-control.handle.left{left:0;top:50%}.react-flow__resize-control.handle.right{left:100%;top:50%}.react-flow__resize-control.handle.top{left:50%;top:0}.react-flow__resize-control.handle.bottom{left:50%;top:100%}.react-flow__resize-control.handle.top.left,.react-flow__resize-control.handle.bottom.left{left:0}.react-flow__resize-control.handle.top.right,.react-flow__resize-control.handle.bottom.right{left:100%}.react-flow__resize-control.line{border-color:var(--xy-resize-background-color, var(--xy-resize-background-color-default));border-width:0;border-style:solid}.react-flow__resize-control.line.left,.react-flow__resize-control.line.right{width:1px;transform:translate(-50%);top:0;height:100%}.react-flow__resize-control.line.left{left:0;border-left-width:1px}.react-flow__resize-control.line.right{left:100%;border-right-width:1px}.react-flow__resize-control.line.top,.react-flow__resize-control.line.bottom{height:1px;transform:translateY(-50%);left:0;width:100%}.react-flow__resize-control.line.top{top:0;border-top-width:1px}.react-flow__resize-control.line.bottom{border-bottom-width:1px;top:100%}.react-flow__edge-textbg{fill:var(--xy-edge-label-background-color, var(--xy-edge-label-background-color-default))}.react-flow__edge-text{fill:var(--xy-edge-label-color, var(--xy-edge-label-color-default))}._container_18lbh_1{position:relative;width:300px}._inputWrapper_18lbh_11{position:relative}._input_18lbh_11{width:100%;padding:var(--spacing-2) var(--spacing-8) var(--spacing-2) var(--spacing-3);background-color:var(--color-bg-surface);border:1px solid var(--color-border-default);border-radius:var(--radius-md);font-size:var(--font-size-body-sm);font-family:var(--font-family-sans);color:var(--color-text-primary);outline:none;box-sizing:border-box;transition:var(--transition-colors),box-shadow var(--duration-normal) var(--ease-smooth)}._input_18lbh_11::placeholder{color:var(--color-text-muted);font-style:italic}._input_18lbh_11:focus{border-color:var(--color-border-focus);box-shadow:var(--shadow-glow-primary)}._clearButton_18lbh_67{position:absolute;right:var(--spacing-2);top:50%;transform:translateY(-50%);background:none;border:none;cursor:pointer;font-size:18px;color:var(--color-text-muted);padding:0 var(--spacing-1);line-height:1;transition:var(--transition-colors)}._clearButton_18lbh_67:hover{color:var(--color-text-secondary)}._dropdown_18lbh_105{position:absolute;top:100%;left:0;right:0;margin-top:var(--spacing-1);background-color:var(--color-bg-surface);border:1px solid var(--color-border-default);border-radius:var(--radius-md);box-shadow:var(--shadow-lg);max-height:300px;overflow-y:auto;z-index:1000}._dropdownEmpty_18lbh_135{padding:var(--spacing-3);color:var(--color-text-muted);font-size:var(--font-size-body-sm);text-align:center}._dropdownItem_18lbh_149{padding:var(--spacing-2-5) var(--spacing-3);cursor:pointer;border-bottom:1px solid var(--color-border-subtle);transition:var(--transition-colors)}._dropdownItem_18lbh_149:last-child{border-bottom:none}._dropdownItem_18lbh_149:hover{background-color:var(--color-bg-elevated)}._correlationId_18lbh_179{font-family:var(--font-family-mono);font-size:var(--font-size-body-xs);font-weight:var(--font-weight-medium);color:var(--color-text-primary);margin-bottom:var(--spacing-1);word-break:break-all}._metadata_18lbh_197{font-size:var(--font-size-caption);color:var(--color-text-tertiary)}._container_kluuc_1{display:flex;flex-direction:column;gap:var(--spacing-2)}._presetButtons_kluuc_13{display:flex;flex-wrap:wrap;gap:var(--spacing-2);align-items:center}._presetButton_kluuc_13{padding:var(--spacing-2) var(--spacing-4);background-color:var(--color-bg-surface);color:var(--color-text-secondary);border:1px solid var(--color-border-default);border-radius:var(--radius-md);cursor:pointer;font-size:var(--font-size-body-sm);font-weight:var(--font-weight-medium);font-family:var(--font-family-sans);transition:var(--transition-colors);white-space:nowrap}._presetButton_kluuc_13:hover{background-color:var(--color-bg-overlay);border-color:var(--color-border-strong)}._presetButton_kluuc_13._active_kluuc_65{background-color:var(--color-primary-600);color:var(--color-text-on-primary);border-color:var(--color-primary-600)}._presetButton_kluuc_13._active_kluuc_65:hover{background-color:var(--color-primary-700);border-color:var(--color-primary-700)}._presetButtonAll_kluuc_87{background:#c241f426;color:var(--color-secondary-200);border-color:var(--color-secondary-500)}._presetButtonAll_kluuc_87:hover{background:#c241f440;border-color:var(--color-secondary-400);color:var(--color-secondary-100)}._presetButtonAll_kluuc_87._active_kluuc_65{background:var(--color-secondary-500);border-color:var(--color-secondary-300);color:var(--color-text-on-primary)}._presetButtonAll_kluuc_87._active_kluuc_65:hover{background:var(--color-secondary-400);border-color:var(--color-secondary-200)}._customRange_kluuc_133{display:flex;gap:var(--spacing-3);align-items:center;padding:var(--spacing-2);background-color:var(--color-bg-surface);border-radius:var(--radius-md);border:1px solid var(--color-border-subtle)}._dateInputGroup_kluuc_153{display:flex;flex-direction:column;gap:var(--spacing-1)}._dateLabel_kluuc_165{font-size:var(--font-size-caption);color:var(--color-text-tertiary);font-weight:var(--font-weight-medium)}._dateInput_kluuc_153{padding:var(--spacing-1-5) var(--spacing-2);background-color:var(--color-bg-elevated);border:1px solid var(--color-border-default);border-radius:var(--radius-md);font-size:var(--font-size-body-sm);font-family:var(--font-family-sans);color:var(--color-text-primary);outline:none;transition:var(--transition-colors),box-shadow var(--duration-normal) var(--ease-smooth)}._dateInput_kluuc_153:focus{border-color:var(--color-border-focus);box-shadow:var(--shadow-glow-primary)}._dateInput_kluuc_153::-webkit-calendar-picker-indicator{cursor:pointer;filter:invert(.7);transition:var(--transition-opacity)}._dateInput_kluuc_153::-webkit-calendar-picker-indicator:hover{filter:invert(1)}._container_9ted7_1{display:flex;flex-direction:column;gap:var(--gap-xs)}._controlsRow_9ted7_13{display:flex;align-items:center;gap:var(--gap-sm);flex-wrap:wrap}._select_9ted7_27{min-width:180px;padding:var(--spacing-1) var(--spacing-2);border-radius:var(--radius-sm);border:1px solid var(--color-border-subtle);background:#00000059;color:var(--color-text-primary)}._saveButton_9ted7_45,._applyButton_9ted7_47,._deleteButton_9ted7_49{padding:var(--spacing-1) var(--spacing-3);border-radius:var(--radius-sm);border:none;font-size:var(--font-size-body-xs);cursor:pointer;transition:background-color var(--duration-fast) ease}._saveButton_9ted7_45{background:var(--color-info);color:var(--color-text-on-primary)}._applyButton_9ted7_47{background:var(--color-success);color:var(--color-text-on-primary)}._deleteButton_9ted7_49{background:var(--color-error);color:var(--color-text-on-primary)}._saveButton_9ted7_45:disabled,._applyButton_9ted7_47:disabled,._deleteButton_9ted7_49:disabled,._select_9ted7_27:disabled{opacity:.5;cursor:not-allowed}._error_9ted7_113{font-size:var(--font-size-body-xs);color:var(--color-error)}._panel_knkln_1{position:fixed;top:0;left:0;bottom:0;width:420px;background:var(--color-glass-bg);-webkit-backdrop-filter:blur(var(--blur-lg));backdrop-filter:blur(var(--blur-lg));border-right:var(--border-default);box-shadow:var(--shadow-2xl);z-index:1100;animation:_slideInLeft_knkln_1 var(--duration-slow) var(--ease-smooth);display:flex;flex-direction:column}._header_knkln_33{display:flex;align-items:flex-start;justify-content:space-between;gap:var(--space-component-sm);padding:var(--space-layout-md);border-bottom:var(--border-subtle)}._title_knkln_51{margin:0;font-size:var(--font-size-h3);color:var(--color-text-primary)}._subtitle_knkln_63{margin:0;font-size:var(--font-size-body-xs);color:var(--color-text-tertiary)}._closeButton_knkln_75{width:32px;height:32px;border-radius:var(--radius-md);border:none;background:transparent;color:var(--color-text-secondary);font-size:22px;cursor:pointer;transition:var(--transition-all)}._closeButton_knkln_75:hover{background:var(--color-bg-overlay);color:var(--color-text-primary)}._content_knkln_109{flex:1;overflow-y:auto;padding:var(--space-layout-md);display:flex;flex-direction:column;gap:var(--space-layout-md)}._section_knkln_127{display:flex;flex-direction:column;gap:var(--space-component-sm)}._sectionLabel_knkln_139{margin:0;font-size:var(--font-size-body-xs);letter-spacing:var(--letter-spacing-wide);color:var(--color-text-tertiary);text-transform:uppercase}._separator_knkln_155{width:100%;height:1px;background:linear-gradient(90deg,transparent,rgba(148,163,184,.25),transparent);margin:var(--space-component-md) 0}@keyframes _slideInLeft_knkln_1{0%{transform:translate(-40px);opacity:0}to{transform:translate(0);opacity:1}}@media (max-width: 960px){._panel_knkln_1{width:100%}}._wrapper_1qq57_1{display:flex;align-items:center;width:100%;gap:var(--gap-md)}._container_1qq57_15{display:inline-flex;align-items:center;flex-wrap:wrap;gap:var(--gap-md);pointer-events:auto;margin-left:0;padding:0;max-width:100%}._toggleButton_1qq57_37{display:inline-flex;align-items:center;gap:var(--gap-sm);padding:var(--spacing-1) var(--spacing-3);border-radius:var(--radius-full);border:var(--border-subtle);background:color-mix(in srgb,var(--color-bg-surface) 80%,transparent);color:var(--color-text-secondary);font-size:var(--font-size-body-sm);font-weight:var(--font-weight-medium);letter-spacing:var(--letter-spacing-wide);text-transform:uppercase;cursor:pointer;transition:var(--transition-colors),var(--transition-transform),var(--transition-shadow)}._toggleButton_1qq57_37:hover{color:var(--color-text-primary);border-color:color-mix(in srgb,var(--color-border-focus) 60%,transparent);background:color-mix(in srgb,var(--color-bg-overlay) 75%,transparent)}._toggleButton_1qq57_37:focus-visible{outline:none;box-shadow:var(--shadow-glow-primary);color:var(--color-text-primary)}._toggleButton_1qq57_37:active{transform:scale(.98)}._toggleButtonActive_1qq57_103{color:var(--color-text-on-primary);background:linear-gradient(135deg,var(--color-primary-500) 0%,var(--color-primary-600) 100%);border-color:color-mix(in srgb,var(--color-primary-400) 70%,transparent);box-shadow:var(--shadow-sm)}._toggleButtonActive_1qq57_103:hover{box-shadow:var(--shadow-md)}._toggleIcon_1qq57_125{display:inline-flex;width:1rem;height:1rem}._toggleIcon_1qq57_125 svg{width:100%;height:100%}._toggleButtonActive_1qq57_103 ._toggleIcon_1qq57_125{color:var(--color-text-on-primary)}._toggleLabel_1qq57_155{letter-spacing:var(--letter-spacing-wide)}._pill_1qq57_163{--pill-accent: var(--color-primary-500);--pill-accent-soft: color-mix(in srgb, var(--color-bg-overlay) 88%, var(--pill-accent) 12%);--pill-border: color-mix(in srgb, var(--pill-accent) 45%, transparent);--pill-shadow: 0 12px 28px -18px color-mix(in srgb, var(--pill-accent) 40%, transparent);display:inline-flex;align-items:center;gap:var(--gap-sm);padding:var(--spacing-1-5) var(--spacing-3);border-radius:var(--radius-full);background:var(--color-bg-overlay);background:linear-gradient(135deg,var(--pill-accent-soft) 0%,color-mix(in srgb,var(--color-bg-surface) 92%,transparent) 100%);border:1px solid var(--pill-border);color:var(--color-text-primary);box-shadow:var(--shadow-xs),var(--pill-shadow);transition:var(--transition-transform),var(--transition-shadow),var(--transition-colors);cursor:default;animation:_fadeIn_1qq57_1 var(--duration-normal) var(--ease-out)}._pill_1qq57_163:hover{transform:translateY(-2px);box-shadow:0 16px 32px -18px color-mix(in srgb,var(--pill-accent) 55%,transparent)}._pill_1qq57_163:focus-within{box-shadow:0 16px 32px -18px color-mix(in srgb,var(--pill-accent) 55%,transparent),0 0 0 2px color-mix(in srgb,var(--pill-accent) 35%,transparent)}._pillAccent_1qq57_227{width:.75rem;height:.75rem;border-radius:var(--radius-full);flex-shrink:0;background:var(--pill-accent);box-shadow:0 0 0 2px color-mix(in srgb,var(--pill-accent) 25%,transparent)}._textGroup_1qq57_245{display:flex;flex-direction:column;gap:2px;line-height:1.1}._pillTitle_1qq57_259{font-size:var(--font-size-tiny);font-weight:var(--font-weight-medium);letter-spacing:var(--letter-spacing-wide);text-transform:uppercase;color:var(--color-text-tertiary)}._pillValue_1qq57_275{font-size:var(--font-size-body-sm);font-weight:var(--font-weight-semibold);color:var(--color-text-primary);line-height:1.3}._removeButton_1qq57_289{background:none;border:none;margin-left:var(--gap-sm);display:inline-flex;align-items:center;justify-content:center;width:1.75rem;height:1.75rem;border-radius:var(--radius-full);color:var(--color-text-tertiary);transition:var(--transition-transform),var(--transition-colors),var(--transition-shadow);cursor:pointer}._removeButton_1qq57_289:hover,._removeButton_1qq57_289:focus-visible{color:var(--color-text-primary);background:color-mix(in srgb,var(--pill-accent) 18%,transparent)}._removeButton_1qq57_289:focus-visible{outline:none;box-shadow:0 0 0 2px color-mix(in srgb,var(--pill-accent) 35%,transparent)}._removeButton_1qq57_289:active{transform:scale(.92)}._removeIcon_1qq57_349{font-size:var(--font-size-body);line-height:1}._pill_1qq57_163[data-filter-type=timeRange]{--pill-accent: var(--color-tertiary-500)}._pill_1qq57_163[data-filter-type=artifactTypes]{--pill-accent: var(--color-secondary-500)}._pill_1qq57_163[data-filter-type=producers]{--pill-accent: var(--color-success)}._pill_1qq57_163[data-filter-type=tags]{--pill-accent: var(--color-secondary-400)}._pill_1qq57_163[data-filter-type=visibility]{--pill-accent: var(--color-info)}@media (max-width: 768px){._wrapper_1qq57_1{width:100%}._container_1qq57_15{border-radius:var(--radius-xl);width:100%}}@keyframes _fadeIn_1qq57_1{0%{opacity:0;transform:translateY(6px)}to{opacity:1;transform:translateY(0)}}.publish-control-panel{position:fixed;top:0;right:0;bottom:0;width:400px;z-index:1000;background:var(--color-glass-bg);-webkit-backdrop-filter:blur(var(--blur-lg));backdrop-filter:blur(var(--blur-lg));border-left:var(--border-default);box-shadow:var(--shadow-xl);animation:slideInRight var(--duration-slow) var(--ease-smooth)}.publish-control-panel-inner{display:flex;flex-direction:column;height:100%;overflow:hidden}.publish-control-header{display:flex;align-items:center;justify-content:space-between;padding:var(--space-layout-sm);border-bottom:var(--border-subtle);flex-shrink:0}.publish-control-title{font-size:var(--font-size-h3);font-weight:var(--font-weight-semibold);color:var(--color-text-primary);margin:0}.publish-control-close-button{display:flex;align-items:center;justify-content:center;width:32px;height:32px;padding:0;background:transparent;border:none;border-radius:var(--radius-md);color:var(--color-text-secondary);cursor:pointer;transition:var(--transition-all)}.publish-control-close-button:hover{background:var(--color-bg-overlay);color:var(--color-text-primary)}.publish-control-close-button:active{background:var(--color-bg-surface);transform:scale(.95)}.publish-control-content{flex:1;overflow-y:auto;padding:var(--space-layout-sm)}.publish-control-content::-webkit-scrollbar{width:8px}.publish-control-content::-webkit-scrollbar-track{background:var(--color-bg-base)}.publish-control-content::-webkit-scrollbar-thumb{background:var(--color-bg-overlay);border-radius:var(--radius-full)}.publish-control-content::-webkit-scrollbar-thumb:hover{background:var(--color-border-default)}.publish-control__form{display:flex;flex-direction:column;gap:var(--space-component-lg)}.publish-control__field{display:flex;flex-direction:column;gap:var(--gap-sm)}.publish-control__label{font-size:var(--font-size-body-sm);font-weight:var(--font-weight-medium);color:var(--color-text-secondary);line-height:var(--line-height-normal);margin:0}.publish-control__select{width:100%;padding:var(--space-component-sm) var(--space-component-md);padding-right:var(--spacing-8);border-radius:var(--radius-md);font-family:var(--font-family-sans);font-size:var(--font-size-body-sm);line-height:var(--line-height-normal);background:var(--color-bg-elevated);color:var(--color-text-primary);border:var(--border-default);appearance:none;background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 12 12'%3E%3Cpath fill='%2394a3b8' d='M6 9L1 4h10z'/%3E%3C/svg%3E");background-repeat:no-repeat;background-position:right var(--spacing-3) center;cursor:pointer;transition:var(--transition-colors),var(--transition-shadow)}.publish-control__select:hover:not(:disabled){border-color:var(--color-border-strong)}.publish-control__select:focus{outline:none;border-color:var(--color-border-focus);box-shadow:var(--shadow-glow-primary)}.publish-control__select:disabled{background:var(--color-bg-base);color:var(--color-text-disabled);cursor:not-allowed;opacity:.6}.publish-control__select--error{border-color:var(--color-border-error)}.publish-control__select--error:focus{box-shadow:var(--shadow-glow-error)}.publish-control__input{width:100%;padding:var(--space-component-sm) var(--space-component-md);border-radius:var(--radius-md);font-family:var(--font-family-sans);font-size:var(--font-size-body-sm);line-height:var(--line-height-normal);background:var(--color-bg-elevated);color:var(--color-text-primary);border:var(--border-default);transition:var(--transition-colors),var(--transition-shadow)}.publish-control__input::placeholder{color:var(--color-text-muted)}.publish-control__input:hover:not(:disabled){border-color:var(--color-border-strong)}.publish-control__input:focus{outline:none;border-color:var(--color-border-focus);box-shadow:var(--shadow-glow-primary)}.publish-control__input:disabled{background:var(--color-bg-base);color:var(--color-text-disabled);cursor:not-allowed;opacity:.6}.publish-control__input--error{border-color:var(--color-border-error)}.publish-control__input--error:focus{box-shadow:var(--shadow-glow-error)}.publish-control__textarea{width:100%;padding:var(--space-component-sm) var(--space-component-md);border-radius:var(--radius-md);min-height:180px;font-family:var(--font-family-mono);font-size:var(--font-size-body-sm);line-height:var(--line-height-relaxed);background:var(--color-bg-elevated);color:var(--color-text-primary);border:var(--border-default);resize:vertical;transition:var(--transition-colors),var(--transition-shadow)}.publish-control__textarea::placeholder{color:var(--color-text-muted);font-family:var(--font-family-mono)}.publish-control__textarea:hover:not(:disabled){border-color:var(--color-border-strong)}.publish-control__textarea:focus{outline:none;border-color:var(--color-border-focus);box-shadow:var(--shadow-glow-primary)}.publish-control__textarea:disabled{background:var(--color-bg-base);color:var(--color-text-disabled);cursor:not-allowed;opacity:.6}.publish-control__textarea--error{border-color:var(--color-border-error)}.publish-control__textarea--error:focus{box-shadow:var(--shadow-glow-error)}.publish-control__checkbox-wrapper{display:flex;align-items:center;gap:var(--gap-sm);padding:var(--space-component-sm) 0}.publish-control__checkbox{width:18px;height:18px;accent-color:var(--color-primary-500);cursor:pointer;transition:var(--transition-colors)}.publish-control__checkbox:disabled{cursor:not-allowed;opacity:.5}.publish-control__checkbox:focus-visible{outline:2px solid var(--color-border-focus);outline-offset:2px;border-radius:var(--radius-sm)}.publish-control__checkbox-label{font-size:var(--font-size-body-sm);font-weight:var(--font-weight-regular);color:var(--color-text-secondary);line-height:var(--line-height-normal);cursor:pointer;-webkit-user-select:none;user-select:none;margin:0}.publish-control__checkbox:disabled+.publish-control__checkbox-label{cursor:not-allowed;opacity:.5}.publish-control__submit{width:100%;padding:var(--space-component-sm) var(--space-component-lg);border-radius:var(--radius-md);border:none;font-family:var(--font-family-sans);font-size:var(--font-size-body-sm);font-weight:var(--font-weight-semibold);line-height:var(--line-height-normal);background:var(--color-primary-500);color:var(--color-text-on-primary);box-shadow:var(--shadow-sm);cursor:pointer;transition:var(--transition-colors),var(--transition-shadow);-webkit-user-select:none;user-select:none}.publish-control__submit:hover:not(:disabled){background:var(--color-primary-600);box-shadow:var(--shadow-md);transform:translateY(-1px)}.publish-control__submit:active:not(:disabled){background:var(--color-primary-700);box-shadow:var(--shadow-xs);transform:translateY(0)}.publish-control__submit:focus-visible{outline:none;box-shadow:var(--shadow-glow-primary)}.publish-control__submit:disabled{background:var(--color-bg-overlay);color:var(--color-text-disabled);cursor:not-allowed;box-shadow:none;transform:none;opacity:.6}.publish-control__error-text{font-size:var(--font-size-caption);font-weight:var(--font-weight-regular);line-height:var(--line-height-normal);color:var(--color-error-light);margin:0;animation:slideDown var(--duration-fast) var(--ease-out)}.publish-control__message{padding:var(--space-component-md);border-radius:var(--radius-md);font-size:var(--font-size-body-sm);font-weight:var(--font-weight-regular);line-height:var(--line-height-normal);border:var(--border-width-1) solid;animation:slideDown var(--duration-normal) var(--ease-out)}.publish-control__message--success{background:var(--color-success-bg);color:var(--color-success-light);border-color:var(--color-success-border)}.publish-control__message--error{background:var(--color-error-bg);color:var(--color-error-light);border-color:var(--color-error-border)}@keyframes slideDown{0%{opacity:0;transform:translateY(-8px)}to{opacity:1;transform:translateY(0)}}.publish-control__field-hint{font-size:var(--font-size-caption);font-weight:var(--font-weight-regular);color:var(--color-text-tertiary);font-style:italic}.publish-control__hint{font-size:var(--font-size-body-sm);font-weight:var(--font-weight-regular);color:var(--color-text-secondary);line-height:var(--line-height-normal);margin:0;padding:var(--space-component-md);text-align:center;opacity:.7}@media (prefers-reduced-motion: reduce){.publish-control-panel{animation-duration:.01ms!important}.publish-control__submit,.publish-control__select,.publish-control__input,.publish-control__textarea,.publish-control__checkbox,.publish-control__message,.publish-control__error-text,.publish-control-close-button{animation-duration:.01ms!important;transition-duration:.01ms!important}.publish-control__submit:hover:not(:disabled){transform:none}}@media (max-width: 768px){.publish-control-panel{width:100%;left:0}}.settings-panel{position:fixed;top:0;right:0;bottom:0;width:550px;z-index:1000;background:var(--color-glass-bg);-webkit-backdrop-filter:blur(var(--blur-lg));backdrop-filter:blur(var(--blur-lg));border-left:var(--border-default);box-shadow:var(--shadow-xl);animation:slideInRight var(--duration-slow) var(--ease-smooth)}.settings-panel-inner{display:flex;flex-direction:column;height:100%;overflow:hidden}.settings-header{display:flex;align-items:center;justify-content:space-between;padding:var(--space-layout-sm);border-bottom:var(--border-subtle);flex-shrink:0}.settings-title{font-size:var(--font-size-h3);font-weight:var(--font-weight-semibold);color:var(--color-text-primary);margin:0}.settings-close-button{display:flex;align-items:center;justify-content:center;width:32px;height:32px;padding:0;background:transparent;border:none;border-radius:var(--radius-md);color:var(--color-text-secondary);cursor:pointer;transition:var(--transition-all)}.settings-close-button:hover{background:var(--color-bg-overlay);color:var(--color-text-primary)}.settings-close-button:active{background:var(--color-bg-surface);transform:scale(.95)}.settings-tabs{display:flex;gap:var(--gap-xs);padding:var(--space-component-md);border-bottom:var(--border-subtle);flex-shrink:0}.settings-tab{display:flex;align-items:center;gap:var(--gap-xs);padding:var(--space-component-sm) var(--space-component-md);background:transparent;border:none;border-radius:var(--radius-md);color:var(--color-text-secondary);font-size:var(--font-size-body-sm);font-weight:var(--font-weight-medium);cursor:pointer;transition:var(--transition-all);position:relative}.settings-tab svg{width:16px;height:16px}.settings-tab:hover{background:var(--color-bg-overlay);color:var(--color-text-primary)}.settings-tab.active{background:var(--color-bg-surface);color:var(--color-primary-500);box-shadow:var(--shadow-sm)}.settings-tab.active:after{content:"";position:absolute;bottom:0;left:50%;transform:translate(-50%);width:40%;height:2px;background:var(--color-primary-500);border-radius:var(--radius-full)}.settings-content{flex:1;overflow-y:auto;padding:var(--space-layout-sm)}.settings-content::-webkit-scrollbar{width:8px}.settings-content::-webkit-scrollbar-track{background:var(--color-bg-base)}.settings-content::-webkit-scrollbar-thumb{background:var(--color-bg-overlay);border-radius:var(--radius-full)}.settings-content::-webkit-scrollbar-thumb:hover{background:var(--color-border-default)}.settings-footer{display:flex;align-items:center;justify-content:space-between;padding:var(--space-component-md);border-top:var(--border-subtle);flex-shrink:0}.settings-footer-left{display:flex;align-items:center}.settings-reset-button{padding:var(--space-component-sm) var(--space-component-md);background:transparent;border:var(--border-default);border-radius:var(--radius-md);color:var(--color-text-secondary);font-size:var(--font-size-body-sm);font-weight:var(--font-weight-medium);cursor:pointer;transition:var(--transition-all)}.settings-reset-button:hover{background:var(--color-bg-overlay);border-color:var(--color-border-strong);color:var(--color-text-primary)}.settings-reset-button:active{background:var(--color-bg-surface);transform:scale(.98)}.settings-section{margin-bottom:var(--space-layout-md)}.settings-section:last-child{margin-bottom:0}.settings-section-title{font-size:var(--font-size-body-md);font-weight:var(--font-weight-semibold);color:var(--color-text-primary);margin:0 0 var(--space-component-md) 0;padding-bottom:var(--space-component-sm);border-bottom:var(--border-subtle)}.settings-field{display:flex;flex-direction:column;gap:var(--gap-xs);margin-bottom:var(--space-component-lg)}.settings-label{font-size:var(--font-size-body-sm);font-weight:var(--font-weight-medium);color:var(--color-text-secondary)}.settings-description{font-size:var(--font-size-caption);color:var(--color-text-tertiary);margin:0}.settings-select,.settings-input{width:100%;padding:var(--space-component-sm) var(--space-component-md);background:var(--color-bg-elevated);border:var(--border-default);border-radius:var(--radius-md);color:var(--color-text-primary);font-size:var(--font-size-body-sm);font-family:var(--font-family-sans);transition:var(--transition-all)}.settings-select:hover,.settings-input:hover{border-color:var(--color-border-strong)}.settings-select:focus,.settings-input:focus{outline:none;border-color:var(--color-border-focus);box-shadow:var(--shadow-glow-primary)}.settings-checkbox-wrapper{display:flex;align-items:center;gap:var(--gap-sm);padding:var(--space-component-sm) 0}.settings-checkbox{width:18px;height:18px;accent-color:var(--color-primary-500);cursor:pointer}.settings-checkbox-label{font-size:var(--font-size-body-sm);color:var(--color-text-secondary);cursor:pointer;-webkit-user-select:none;user-select:none}@keyframes slideInRight{0%{transform:translate(100%);opacity:0}to{transform:translate(0);opacity:1}}@media (prefers-reduced-motion: reduce){.settings-panel{animation-duration:.01ms!important}.settings-tab,.settings-close-button,.settings-reset-button{transition-duration:.01ms!important}}@media (max-width: 768px){.settings-panel{width:100%;left:0}}.keyboard-shortcuts-overlay{position:fixed;inset:0;background:var(--color-overlay);backdrop-filter:blur(var(--blur-sm));-webkit-backdrop-filter:blur(var(--blur-sm));display:flex;align-items:center;justify-content:center;z-index:1000;animation:fadeIn var(--duration-normal) var(--ease-smooth)}@keyframes fadeIn{0%{opacity:0}to{opacity:1}}.keyboard-shortcuts-dialog{background:var(--color-bg-surface);border:var(--border-default);border-radius:var(--radius-lg);box-shadow:var(--shadow-xl);max-width:600px;width:90%;max-height:80vh;display:flex;flex-direction:column;animation:slideInUp var(--duration-normal) var(--ease-smooth)}@keyframes slideInUp{0%{opacity:0;transform:translateY(20px) scale(.98)}to{opacity:1;transform:translateY(0) scale(1)}}.keyboard-shortcuts-header{display:flex;justify-content:space-between;align-items:center;padding:var(--space-layout-sm) var(--space-layout-md);border-bottom:var(--border-subtle)}.keyboard-shortcuts-title{margin:0;font-size:var(--font-size-h4);font-weight:var(--font-weight-semibold);color:var(--color-text-primary);letter-spacing:var(--letter-spacing-tight)}.keyboard-shortcuts-close{display:inline-flex;align-items:center;justify-content:center;width:32px;height:32px;padding:0;background:transparent;color:var(--color-text-tertiary);border:none;border-radius:var(--radius-md);cursor:pointer;transition:var(--transition-colors),var(--transition-transform)}.keyboard-shortcuts-close:hover{background:var(--color-bg-overlay);color:var(--color-text-secondary)}.keyboard-shortcuts-close:active{transform:scale(.95)}.keyboard-shortcuts-close:focus-visible{outline:none;box-shadow:var(--shadow-glow-primary)}.keyboard-shortcuts-content{flex:1;overflow-y:auto;padding:var(--space-layout-md)}.keyboard-shortcuts-category{margin-bottom:var(--space-layout-lg)}.keyboard-shortcuts-category:last-child{margin-bottom:0}.keyboard-shortcuts-category-title{margin:0 0 var(--space-component-md) 0;font-size:var(--font-size-body-sm);font-weight:var(--font-weight-semibold);color:var(--color-text-secondary);text-transform:uppercase;letter-spacing:var(--letter-spacing-wide)}.keyboard-shortcuts-list{display:flex;flex-direction:column;gap:var(--gap-sm)}.keyboard-shortcut-item{display:flex;justify-content:space-between;align-items:center;padding:var(--space-component-sm) var(--space-component-md);background:var(--color-bg-elevated);border:var(--border-subtle);border-radius:var(--radius-md);transition:var(--transition-colors)}.keyboard-shortcut-item:hover{background:var(--color-bg-overlay);border-color:var(--color-border-strong)}.keyboard-shortcut-keys{display:flex;align-items:center;gap:var(--gap-xs)}.keyboard-key{display:inline-flex;align-items:center;justify-content:center;min-width:28px;padding:var(--spacing-1) var(--spacing-2);background:var(--color-bg-base);color:var(--color-text-primary);border:var(--border-default);border-radius:var(--radius-sm);font-family:var(--font-family-mono);font-size:var(--font-size-body-sm);font-weight:var(--font-weight-medium);box-shadow:var(--shadow-xs),inset 0 -2px 0 0 var(--color-border-default);line-height:1;white-space:nowrap}.keyboard-key-separator{color:var(--color-text-tertiary);font-size:var(--font-size-caption);font-weight:var(--font-weight-medium)}.keyboard-shortcut-description{color:var(--color-text-secondary);font-size:var(--font-size-body-sm);text-align:right}.keyboard-shortcuts-footer{padding:var(--space-component-md) var(--space-layout-md);border-top:var(--border-subtle);background:var(--color-bg-elevated)}.keyboard-shortcuts-hint{margin:0;text-align:center;color:var(--color-text-tertiary);font-size:var(--font-size-caption)}.keyboard-shortcuts-content::-webkit-scrollbar{width:8px}.keyboard-shortcuts-content::-webkit-scrollbar-track{background:var(--color-bg-elevated)}.keyboard-shortcuts-content::-webkit-scrollbar-thumb{background:var(--color-border-default);border-radius:var(--radius-full);transition:var(--transition-colors)}.keyboard-shortcuts-content::-webkit-scrollbar-thumb:hover{background:var(--color-border-strong)}@media (max-width: 768px){.keyboard-shortcuts-dialog{max-width:95%;max-height:90vh}.keyboard-shortcut-item{flex-direction:column;align-items:flex-start;gap:var(--gap-sm)}.keyboard-shortcut-description{text-align:left}}@media (prefers-reduced-motion: reduce){.keyboard-shortcuts-overlay,.keyboard-shortcuts-dialog{animation:none}.keyboard-shortcuts-close{transition:none}}._connectionBadge_kl6ey_1{display:flex;align-items:center;gap:var(--gap-sm);padding:var(--spacing-1-5) var(--spacing-3);border-radius:var(--radius-full);font-size:var(--font-size-caption);font-weight:var(--font-weight-medium);box-shadow:var(--shadow-xs);transition:var(--transition-all);cursor:default}._connectionBadge_kl6ey_1._hasError_kl6ey_27{cursor:help}._connectionBadge_kl6ey_1._connected_kl6ey_37{background-color:var(--color-success-bg);color:var(--color-success-dark);border:var(--border-width-1) solid var(--color-success-border)}._connectionBadge_kl6ey_1._connecting_kl6ey_49,._connectionBadge_kl6ey_1._reconnecting_kl6ey_51{background-color:var(--color-warning-bg);color:var(--color-warning-dark);border:var(--border-width-1) solid var(--color-warning-border)}._connectionBadge_kl6ey_1._disconnected_kl6ey_63{background-color:var(--color-error-bg);color:var(--color-error-dark);border:var(--border-width-1) solid var(--color-error-border)}._statusIndicator_kl6ey_77{width:8px;height:8px;border-radius:var(--radius-circle);transition:var(--transition-opacity)}._statusIndicator_kl6ey_77._connected_kl6ey_37{background-color:var(--color-success)}._statusIndicator_kl6ey_77._connecting_kl6ey_49,._statusIndicator_kl6ey_77._reconnecting_kl6ey_51{background-color:var(--color-warning);animation:_statusPulse_kl6ey_1 2s var(--ease-smooth) infinite}._statusIndicator_kl6ey_77._disconnected_kl6ey_63{background-color:var(--color-error)}._statusText_kl6ey_121{line-height:var(--line-height-snug);letter-spacing:var(--letter-spacing-normal)}@keyframes _statusPulse_kl6ey_1{0%,to{opacity:1;transform:scale(1)}50%{opacity:.5;transform:scale(.95)}}@media (prefers-reduced-motion: reduce){._statusIndicator_kl6ey_77._connecting_kl6ey_49,._statusIndicator_kl6ey_77._reconnecting_kl6ey_51{animation:none}._connectionBadge_kl6ey_1{transition:none}}.dashboard-layout{width:100vw;height:100vh;display:flex;flex-direction:column;background:var(--color-bg-base);overflow:hidden}.dashboard-header{display:flex;justify-content:space-between;align-items:center;gap:var(--space-layout-md);padding:var(--space-component-md) var(--space-layout-sm);background:var(--color-bg-surface);border-bottom:var(--border-subtle);box-shadow:var(--shadow-sm);z-index:100}.filter-pills-bar{position:relative;padding:var(--spacing-1-5) var(--space-layout-md);background:color-mix(in srgb,var(--color-bg-overlay) 65%,transparent);border-bottom:var(--border-subtle);-webkit-backdrop-filter:blur(var(--blur-sm));backdrop-filter:blur(var(--blur-sm));min-height:0;display:flex;align-items:center;gap:var(--gap-md);z-index:90}.dashboard-title{margin:0;font-size:var(--font-size-h3);font-weight:var(--font-weight-semibold);color:var(--color-text-primary);letter-spacing:var(--letter-spacing-tight);white-space:nowrap}.view-toggle-container{display:flex;align-items:center;gap:var(--gap-md);flex:1;justify-content:center}.view-toggle-label{font-size:var(--font-size-body-sm);font-weight:var(--font-weight-medium);color:var(--color-text-tertiary);letter-spacing:var(--letter-spacing-wide);text-transform:uppercase;font-size:var(--font-size-caption)}.view-toggle-group{display:inline-flex;background:var(--color-bg-elevated);padding:var(--spacing-1);border-radius:var(--radius-full);border:var(--border-subtle);box-shadow:var(--shadow-inner);gap:var(--gap-xs)}.view-toggle-button{position:relative;padding:var(--space-component-sm) var(--space-component-lg);background:transparent;color:var(--color-text-tertiary);border:none;border-radius:var(--radius-full);font-family:var(--font-family-sans);font-size:var(--font-size-body-sm);font-weight:var(--font-weight-medium);cursor:pointer;transition:var(--transition-colors),var(--transition-transform);white-space:nowrap}.view-toggle-button:hover:not(.active){color:var(--color-text-secondary);background:var(--color-bg-overlay)}.view-toggle-button.active{background:var(--color-primary-500);color:var(--color-text-on-primary);box-shadow:var(--shadow-sm)}.view-toggle-button:active{transform:scale(.98)}.view-toggle-button:focus-visible{outline:none;box-shadow:var(--shadow-glow-primary)}.dashboard-actions{display:flex;align-items:center;gap:var(--gap-md)}.icon-button{display:inline-flex;align-items:center;justify-content:center;width:32px;height:32px;padding:var(--spacing-2);background:transparent;color:var(--color-text-tertiary);border:none;border-radius:var(--radius-md);cursor:pointer;transition:var(--transition-colors),var(--transition-transform)}.icon-button:hover{background:var(--color-bg-overlay);color:var(--color-text-secondary)}.icon-button:active{transform:scale(.95)}.icon-button:focus-visible{outline:none;box-shadow:var(--shadow-glow-primary)}.help-button:hover{color:var(--color-primary-500);background:var(--color-primary-50)}.help-button:focus-visible{box-shadow:var(--shadow-glow-primary)}.clear-button:hover{color:var(--color-error);background:var(--color-error-bg)}.clear-button:focus-visible{box-shadow:var(--shadow-glow-error)}.controls-toggle{display:inline-flex;align-items:center;gap:var(--gap-sm);padding:var(--space-component-sm) var(--space-component-md);background:var(--color-bg-elevated);color:var(--color-text-secondary);border:var(--border-default);border-radius:var(--radius-md);font-family:var(--font-family-sans);font-size:var(--font-size-body-sm);font-weight:var(--font-weight-medium);cursor:pointer;transition:var(--transition-colors),var(--transition-shadow),var(--transition-transform);white-space:nowrap}.controls-toggle.primary{background:var(--color-primary-500);color:var(--color-text-on-primary);border-color:var(--color-primary-500);box-shadow:var(--shadow-md);font-weight:var(--font-weight-semibold)}.controls-toggle.primary:hover{background:var(--color-primary-600);border-color:var(--color-primary-600);box-shadow:var(--shadow-lg)}.controls-toggle.primary.active{background:var(--color-primary-700);border-color:var(--color-primary-700)}.controls-toggle:hover{background:var(--color-bg-surface);color:var(--color-text-primary);border-color:var(--color-border-strong);box-shadow:var(--shadow-sm)}.controls-toggle.active{background:var(--color-success);color:var(--color-text-on-primary);border-color:var(--color-success);box-shadow:var(--shadow-sm)}.controls-toggle.active:hover{background:var(--color-success-dark);border-color:var(--color-success-dark)}.controls-toggle:active{transform:scale(.98)}.controls-toggle:focus-visible{outline:none;box-shadow:var(--shadow-glow-primary)}.controls-toggle.active:focus-visible{box-shadow:var(--shadow-glow-success)}.controls-toggle svg{width:16px;height:16px;flex-shrink:0;transition:var(--transition-transform)}.controls-toggle.active svg{transform:rotate(45deg)}.dashboard-main{flex:1;display:flex;overflow:hidden;position:relative}.graph-container{flex:1;overflow:hidden;position:relative}.controls-sidebar{width:400px;background:var(--color-glass-bg);backdrop-filter:blur(var(--blur-lg));-webkit-backdrop-filter:blur(var(--blur-lg));border-left:var(--border-subtle);box-shadow:var(--shadow-lg);overflow-y:auto;animation:slideInRight var(--duration-slow) var(--ease-smooth)}@keyframes slideInRight{0%{opacity:0;transform:translate(20px)}to{opacity:1;transform:translate(0)}}.controls-sidebar-inner{padding:var(--space-layout-sm)}.controls-title{margin:0 0 var(--space-layout-sm) 0;font-size:var(--font-size-h4);font-weight:var(--font-weight-semibold);color:var(--color-text-primary);letter-spacing:var(--letter-spacing-tight)}.control-section{margin-bottom:var(--space-layout-md)}.control-section-title{margin:0 0 var(--space-component-md) 0;font-size:var(--font-size-h5);font-weight:var(--font-weight-medium);color:var(--color-text-secondary)}.controls-sidebar::-webkit-scrollbar{width:8px}.controls-sidebar::-webkit-scrollbar-track{background:var(--color-bg-elevated)}.controls-sidebar::-webkit-scrollbar-thumb{background:var(--color-border-default);border-radius:var(--radius-full);transition:var(--transition-colors)}.controls-sidebar::-webkit-scrollbar-thumb:hover{background:var(--color-border-strong)}@media (max-width: 1024px){.dashboard-header{flex-wrap:wrap;gap:var(--gap-md)}.view-toggle-container{order:3;width:100%;justify-content:center}.controls-sidebar{width:320px}}@media (max-width: 768px){.dashboard-title{font-size:var(--font-size-h4)}.view-toggle-button{padding:var(--spacing-2) var(--spacing-4);font-size:var(--font-size-caption)}.controls-toggle span{display:none}.controls-sidebar{width:280px}}@media (prefers-reduced-motion: reduce){.controls-sidebar{animation:none}.view-toggle-button,.icon-button,.controls-toggle{transition:none}.controls-toggle svg{transition:none}}@media print{.dashboard-header,.controls-sidebar{display:none}.dashboard-main{flex:1}}._container_z8335_5{display:flex;align-items:center;justify-content:center;min-height:400px;padding:var(--space-layout-md);background:var(--color-bg-base)}._content_z8335_23{max-width:500px;text-align:center;padding:var(--space-layout-lg);background:var(--color-bg-surface);border:var(--border-subtle);border-radius:var(--radius-xl);box-shadow:var(--shadow-lg)}._icon_z8335_43{color:var(--color-error);margin-bottom:var(--spacing-6);animation:_shake_z8335_1 .5s var(--ease-smooth)}._title_z8335_55{font-size:var(--font-size-h2);font-weight:var(--font-weight-bold);color:var(--color-text-primary);margin:0 0 var(--spacing-4) 0;line-height:var(--line-height-tight)}._description_z8335_71{font-size:var(--font-size-body);color:var(--color-text-secondary);line-height:var(--line-height-relaxed);margin:0 0 var(--spacing-6) 0}._details_z8335_85{margin:var(--spacing-6) 0;text-align:left;background:var(--color-bg-base);border:var(--border-default);border-radius:var(--radius-md);padding:var(--space-component-md)}._summary_z8335_103{font-size:var(--font-size-body-sm);font-weight:var(--font-weight-semibold);color:var(--color-text-secondary);cursor:pointer;-webkit-user-select:none;user-select:none;padding:var(--spacing-2);margin:calc(var(--space-component-md) * -1);margin-bottom:var(--spacing-3)}._summary_z8335_103:hover{color:var(--color-text-primary)}._errorMessage_z8335_133{font-size:var(--font-size-body-sm);color:var(--color-error-light);margin-bottom:var(--spacing-3);line-height:var(--line-height-relaxed)}._stackTrace_z8335_147{font-family:var(--font-family-mono);font-size:var(--font-size-caption);color:var(--color-text-tertiary);background:var(--color-bg-elevated);padding:var(--space-component-sm);border-radius:var(--radius-sm);overflow-x:auto;white-space:pre-wrap;word-break:break-word;max-height:200px;overflow-y:auto}._actions_z8335_175{display:flex;gap:var(--gap-md);justify-content:center}._primaryButton_z8335_187{padding:var(--space-component-sm) var(--space-component-lg);font-size:var(--font-size-body-sm);font-weight:var(--font-weight-semibold);color:var(--color-text-on-primary);background:var(--color-primary-500);border:none;border-radius:var(--radius-md);cursor:pointer;box-shadow:var(--shadow-sm);transition:var(--transition-colors),var(--transition-shadow)}._primaryButton_z8335_187:hover{background:var(--color-primary-600);box-shadow:var(--shadow-md)}._primaryButton_z8335_187:active{background:var(--color-primary-700);box-shadow:var(--shadow-xs);transform:translateY(1px)}._primaryButton_z8335_187:focus-visible{outline:none;box-shadow:var(--shadow-glow-primary)}._secondaryButton_z8335_245{padding:var(--space-component-sm) var(--space-component-lg);font-size:var(--font-size-body-sm);font-weight:var(--font-weight-semibold);color:var(--color-text-secondary);background:transparent;border:var(--border-default);border-radius:var(--radius-md);cursor:pointer;transition:var(--transition-colors)}._secondaryButton_z8335_245:hover{background:var(--color-bg-overlay);color:var(--color-text-primary);border-color:var(--color-border-strong)}._secondaryButton_z8335_245:active{transform:translateY(1px)}._secondaryButton_z8335_245:focus-visible{outline:none;border-color:var(--color-border-focus);box-shadow:var(--shadow-glow-primary)}@keyframes _shake_z8335_1{0%,to{transform:translate(0)}10%,30%,50%,70%,90%{transform:translate(-4px)}20%,40%,60%,80%{transform:translate(4px)}}@media (prefers-reduced-motion: reduce){._icon_z8335_43{animation:none}}._container_1vp06_1{display:flex;flex-direction:column;gap:var(--space-layout-sm);height:100%;padding:var(--space-layout-sm);background:var(--color-bg-surface)}._header_1vp06_19{display:flex;align-items:center;justify-content:space-between;gap:var(--gap-sm)}._metrics_1vp06_33{display:flex;gap:var(--gap-lg);flex-wrap:wrap}._metricLabel_1vp06_45{display:block;font-size:var(--font-size-overline);color:var(--color-text-tertiary);text-transform:uppercase;letter-spacing:var(--letter-spacing-wider)}._metricValue_1vp06_61{font-size:var(--font-size-body-md);font-weight:var(--font-weight-semibold);color:var(--color-text-primary)}._actions_1vp06_73{display:flex;gap:var(--gap-sm)}._actions_1vp06_73 button{padding:var(--spacing-1) var(--spacing-3);border-radius:var(--radius-sm);border:none;cursor:pointer;background:#6366f140;color:var(--color-text-primary);transition:background-color var(--duration-fast) ease}._actions_1vp06_73 button:disabled{opacity:.5;cursor:not-allowed}._actions_1vp06_73 button:hover:not(:disabled){background:#6366f173}._tableContainer_1vp06_121{display:flex;flex-direction:column;background:#0f172a99;border:1px solid rgba(148,163,184,.1);border-radius:var(--radius-md);overflow:hidden;flex:2 1 0;min-height:0}._contentArea_1vp06_143{display:flex;gap:var(--space-layout-sm);flex:1;min-height:0}._detailPanel_1vp06_157{flex:1 1 0;background:#0f172a80;border:1px solid rgba(148,163,184,.15);border-radius:var(--radius-md);padding:var(--spacing-3);display:flex;flex-direction:column;gap:var(--gap-md);max-height:100%;overflow-y:auto}._headerRow_1vp06_183,._dataRow_1vp06_185{display:grid;grid-template-columns:200px 140px 160px 180px 160px 120px 100px;gap:var(--gap-sm);padding:var(--spacing-2) var(--spacing-3);font-size:var(--font-size-body-xs);align-items:center}._headerRow_1vp06_183{background:#94a3b81a;font-weight:var(--font-weight-semibold);text-transform:uppercase;letter-spacing:var(--letter-spacing-wide)}._dataRow_1vp06_185{border-bottom:1px solid rgba(148,163,184,.08)}._virtualViewport_1vp06_225{overflow-y:auto}._dataRowStripe_1vp06_233{background:#94a3b80d}._dataRow_1vp06_185{cursor:pointer;transition:background-color var(--duration-fast) ease}._dataRow_1vp06_185:focus-visible{outline:2px solid var(--color-primary-400);outline-offset:2px}._dataRowSelected_1vp06_261{background:#6366f140;border-left:3px solid var(--color-primary-400)}._dataRowSelected_1vp06_261 span{color:var(--color-text-primary)}._emptyState_1vp06_279,._loading_1vp06_281,._error_1vp06_283{padding:var(--spacing-4);text-align:center;color:var(--color-text-secondary)}._error_1vp06_283{color:var(--color-error)}._retentionBanner_1vp06_303{display:flex;flex-direction:column;gap:var(--gap-xs);background:#94a3b814;border:1px solid rgba(148,163,184,.15);border-radius:var(--radius-sm);padding:var(--spacing-2) var(--spacing-3);font-size:var(--font-size-body-xs);color:var(--color-text-secondary)}._retentionBanner_1vp06_303 strong{color:var(--color-text-primary);font-weight:var(--font-weight-semibold)}@media (max-width: 1280px){._contentArea_1vp06_143{flex-direction:column}._detailPanel_1vp06_157{max-height:none}}._detailHeader_1vp06_357{display:flex;align-items:flex-start;justify-content:space-between;gap:var(--gap-sm)}._detailHeader_1vp06_357 h3{margin:0;font-size:var(--font-size-body-lg);color:var(--color-text-primary)}._detailHeader_1vp06_357 p{margin:0;font-size:var(--font-size-body-xs);color:var(--color-text-secondary)}._detailHeader_1vp06_357 button{padding:var(--spacing-1) var(--spacing-3);border-radius:var(--radius-sm);border:none;cursor:pointer;background:#6366f133;color:var(--color-primary-50);font-size:var(--font-size-body-xs);text-transform:uppercase;letter-spacing:var(--letter-spacing-wide)}._detailHeader_1vp06_357 button:hover{background:#6366f159}._detailSection_1vp06_427{display:flex;flex-direction:column;gap:var(--gap-sm)}._detailSection_1vp06_427 h4{margin:0;font-size:var(--font-size-body-sm);color:var(--color-text-secondary);text-transform:uppercase;letter-spacing:var(--letter-spacing-wide)}._detailList_1vp06_455{display:grid;grid-template-columns:minmax(110px,.45fr) 1fr;gap:var(--gap-xs) var(--gap-sm);font-size:var(--font-size-body-xs)}._detailList_1vp06_455 dt{color:var(--color-text-tertiary);font-weight:var(--font-weight-semibold)}._detailList_1vp06_455 dd{margin:0;color:var(--color-text-primary);word-break:break-word}._consumptionList_1vp06_491{list-style:none;padding:0;margin:0;display:flex;flex-direction:column;gap:var(--gap-xs)}._consumptionList_1vp06_491 li{display:flex;flex-direction:column;gap:2px;padding:var(--spacing-2);border:1px solid rgba(148,163,184,.18);border-radius:var(--radius-sm);background:#1e293b8c}._consumerName_1vp06_529{font-weight:var(--font-weight-semibold);color:var(--color-text-primary)}._runBadge_1vp06_539{display:inline-flex;align-items:center;justify-content:center;align-self:flex-start;padding:2px 6px;border-radius:var(--radius-xs);font-size:var(--font-size-caption);background:#6366f140;color:var(--color-primary-100);margin-top:2px}._emptyDetail_1vp06_565,._emptyConsumption_1vp06_567{font-size:var(--font-size-body-sm);color:var(--color-text-secondary);margin:0}:root{--color-bg-base: #0a0a0b;--color-bg-elevated: #121214;--color-bg-surface: #1a1a1e;--color-bg-overlay: #232329;--color-bg-float: #2a2a32;--color-primary-50: #eef2ff;--color-primary-100: #e0e7ff;--color-primary-200: #c7d2fe;--color-primary-300: #a5b4fc;--color-primary-400: #818cf8;--color-primary-500: #6366f1;--color-primary-600: #4f46e5;--color-primary-700: #4338ca;--color-primary-800: #3730a3;--color-primary-900: #312e81;--color-secondary-50: #fdf4ff;--color-secondary-100: #fae8ff;--color-secondary-200: #f5d0fe;--color-secondary-300: #f0abfc;--color-secondary-400: #e879f9;--color-secondary-500: #d946ef;--color-secondary-600: #c026d3;--color-secondary-700: #a21caf;--color-secondary-800: #86198f;--color-secondary-900: #701a75;--color-tertiary-50: #ecfeff;--color-tertiary-100: #cffafe;--color-tertiary-200: #a5f3fc;--color-tertiary-300: #67e8f9;--color-tertiary-400: #22d3ee;--color-tertiary-500: #06b6d4;--color-tertiary-600: #0891b2;--color-tertiary-700: #0e7490;--color-tertiary-800: #155e75;--color-tertiary-900: #164e63;--color-success-light: #6ee7b7;--color-success: #10b981;--color-success-dark: #047857;--color-success-bg: rgba(16, 185, 129, .1);--color-success-border: rgba(16, 185, 129, .3);--color-warning-light: #fbbf24;--color-warning: #f59e0b;--color-warning-dark: #d97706;--color-warning-bg: rgba(245, 158, 11, .1);--color-warning-border: rgba(245, 158, 11, .3);--color-error-light: #f87171;--color-error: #ef4444;--color-error-dark: #dc2626;--color-error-bg: rgba(239, 68, 68, .1);--color-error-border: rgba(239, 68, 68, .3);--color-info-light: #60a5fa;--color-info: #3b82f6;--color-info-dark: #2563eb;--color-info-bg: rgba(59, 130, 246, .1);--color-info-border: rgba(59, 130, 246, .3);--color-active-light: #818cf8;--color-active: #6366f1;--color-active-dark: #4f46e5;--color-active-bg: rgba(99, 102, 241, .1);--color-active-border: rgba(99, 102, 241, .3);--color-idle-light: #94a3b8;--color-idle: #64748b;--color-idle-dark: #475569;--color-idle-bg: rgba(100, 116, 139, .1);--color-idle-border: rgba(100, 116, 139, .3);--color-text-primary: #f8fafc;--color-text-secondary: #cbd5e1;--color-text-tertiary: #94a3b8;--color-text-muted: #64748b;--color-text-disabled: #475569;--color-text-on-primary: #ffffff;--color-text-on-dark: #0f172a;--color-border-subtle: #1e293b;--color-border-default: #334155;--color-border-strong: #475569;--color-border-focus: #6366f1;--color-border-error: #ef4444;--color-divider: rgba(148, 163, 184, .1);--color-node-agent-bg: #1e293b;--color-node-agent-border: #3b82f6;--color-node-agent-border-selected: #6366f1;--color-node-agent-text: #f8fafc;--color-node-agent-badge: #334155;--color-node-agent-badge-text: #94a3b8;--color-node-message-bg: #422006;--color-node-message-border: #f59e0b;--color-node-message-border-selected: #d946ef;--color-node-message-text: #fef3c7;--color-node-message-metadata: #a16207;--color-edge-default: #475569;--color-edge-active: #6366f1;--color-edge-message: #f59e0b;--color-edge-error: #ef4444;--color-edge-label-bg: rgba(26, 26, 30, .95);--color-edge-label-text: #cbd5e1;--color-glass-bg: rgba(26, 26, 30, .8);--color-glass-border: rgba(148, 163, 184, .1);--color-overlay-backdrop: rgba(10, 10, 11, .7);--color-modal-backdrop: rgba(10, 10, 11, .85);--font-family-sans: "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Helvetica Neue", Arial, sans-serif;--font-family-mono: "JetBrains Mono", "Fira Code", "Consolas", "Monaco", "Courier New", monospace;--font-family-display: "Inter", -apple-system, BlinkMacSystemFont, sans-serif;--font-size-display-2xl: 72px;--font-size-display-xl: 60px;--font-size-display-lg: 48px;--font-size-display-md: 36px;--font-size-h1: 32px;--font-size-h2: 24px;--font-size-h3: 20px;--font-size-h4: 18px;--font-size-h5: 16px;--font-size-h6: 14px;--font-size-body-xl: 20px;--font-size-body-lg: 18px;--font-size-body: 16px;--font-size-body-sm: 14px;--font-size-body-xs: 12px;--font-size-caption: 12px;--font-size-overline: 10px;--font-size-tiny: 10px;--font-weight-light: 300;--font-weight-regular: 400;--font-weight-medium: 500;--font-weight-semibold: 600;--font-weight-bold: 700;--line-height-tight: 1.1;--line-height-snug: 1.375;--line-height-normal: 1.5;--line-height-relaxed: 1.625;--line-height-loose: 2;--letter-spacing-tight: -.02em;--letter-spacing-normal: 0;--letter-spacing-wide: .025em;--letter-spacing-wider: .05em;--letter-spacing-widest: .1em;--spacing-0: 0;--spacing-0-5: 2px;--spacing-1: 4px;--spacing-1-5: 6px;--spacing-2: 8px;--spacing-3: 12px;--spacing-4: 16px;--spacing-5: 20px;--spacing-6: 24px;--spacing-8: 32px;--spacing-10: 40px;--spacing-12: 48px;--spacing-16: 64px;--spacing-20: 80px;--spacing-24: 96px;--spacing-32: 128px;--spacing-40: 160px;--spacing-48: 192px;--spacing-56: 224px;--spacing-64: 256px;--space-component-xs: var(--spacing-2);--space-component-sm: var(--spacing-3);--space-component-md: var(--spacing-4);--space-component-lg: var(--spacing-6);--space-component-xl: var(--spacing-8);--space-layout-xs: var(--spacing-4);--space-layout-sm: var(--spacing-6);--space-layout-md: var(--spacing-8);--space-layout-lg: var(--spacing-12);--space-layout-xl: var(--spacing-16);--space-layout-2xl: var(--spacing-24);--gap-xs: var(--spacing-1);--gap-sm: var(--spacing-2);--gap-md: var(--spacing-3);--gap-lg: var(--spacing-4);--gap-xl: var(--spacing-6);--shadow-xs: 0 1px 2px 0 rgba(0, 0, 0, .4);--shadow-sm: 0 2px 4px -1px rgba(0, 0, 0, .5), 0 1px 2px -1px rgba(0, 0, 0, .3);--shadow-md: 0 4px 6px -1px rgba(0, 0, 0, .6), 0 2px 4px -1px rgba(0, 0, 0, .4);--shadow-lg: 0 10px 15px -3px rgba(0, 0, 0, .7), 0 4px 6px -2px rgba(0, 0, 0, .5);--shadow-xl: 0 20px 25px -5px rgba(0, 0, 0, .8), 0 10px 10px -5px rgba(0, 0, 0, .6);--shadow-2xl: 0 25px 50px -12px rgba(0, 0, 0, .9);--shadow-glow-primary: 0 0 0 3px rgba(99, 102, 241, .3);--shadow-glow-secondary: 0 0 0 3px rgba(217, 70, 239, .3);--shadow-glow-success: 0 0 0 3px rgba(16, 185, 129, .3);--shadow-glow-error: 0 0 0 3px rgba(239, 68, 68, .3);--shadow-glow-warning: 0 0 0 3px rgba(245, 158, 11, .3);--shadow-inner: inset 0 2px 4px 0 rgba(0, 0, 0, .5);--shadow-inner-lg: inset 0 4px 8px 0 rgba(0, 0, 0, .6);--border-width-0: 0;--border-width-1: 1px;--border-width-2: 2px;--border-width-3: 3px;--border-width-4: 4px;--radius-none: 0;--radius-sm: 4px;--radius-md: 6px;--radius-lg: 8px;--radius-xl: 12px;--radius-2xl: 16px;--radius-3xl: 24px;--radius-full: 9999px;--radius-circle: 50%;--border-subtle: var(--border-width-1) solid var(--color-border-subtle);--border-default: var(--border-width-1) solid var(--color-border-default);--border-strong: var(--border-width-2) solid var(--color-border-strong);--border-focus: var(--border-width-2) solid var(--color-border-focus);--border-error: var(--border-width-2) solid var(--color-border-error);--duration-instant: 0ms;--duration-fast: .1s;--duration-normal: .2s;--duration-slow: .3s;--duration-slower: .4s;--duration-slowest: .5s;--ease-linear: linear;--ease-in: cubic-bezier(.4, 0, 1, 1);--ease-out: cubic-bezier(0, 0, .2, 1);--ease-in-out: cubic-bezier(.4, 0, .2, 1);--ease-smooth: cubic-bezier(.4, 0, .6, 1);--ease-bounce: cubic-bezier(.68, -.55, .265, 1.55);--ease-elastic: cubic-bezier(.175, .885, .32, 1.275);--ease-sharp: cubic-bezier(.4, 0, .6, 1);--transition-colors: color var(--duration-fast) var(--ease-smooth), background-color var(--duration-fast) var(--ease-smooth), border-color var(--duration-fast) var(--ease-smooth);--transition-opacity: opacity var(--duration-normal) var(--ease-out);--transition-transform: transform var(--duration-normal) var(--ease-smooth);--transition-shadow: box-shadow var(--duration-normal) var(--ease-out);--transition-all: all var(--duration-normal) var(--ease-smooth);--transition-base: var(--duration-normal) var(--ease-smooth);--blur-sm: 4px;--blur-md: 8px;--blur-lg: 12px;--blur-xl: 16px;--blur-2xl: 24px}*{margin:0;padding:0;box-sizing:border-box}html{font-size:16px}body{font-family:var(--font-family-sans);font-size:var(--font-size-body);font-weight:var(--font-weight-regular);line-height:var(--line-height-normal);color:var(--color-text-primary);background:var(--color-bg-base);-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}h1,h2,h3,h4,h5,h6{margin:0;font-weight:var(--font-weight-semibold);color:var(--color-text-primary)}h1{font-size:var(--font-size-h1);font-weight:var(--font-weight-bold);line-height:var(--line-height-tight);letter-spacing:var(--letter-spacing-tight)}h2{font-size:var(--font-size-h2);line-height:var(--line-height-tight);letter-spacing:var(--letter-spacing-tight)}h3{font-size:var(--font-size-h3);line-height:var(--line-height-snug)}h4{font-size:var(--font-size-h4);font-weight:var(--font-weight-medium);line-height:var(--line-height-snug)}h5,h6{font-size:var(--font-size-h5);font-weight:var(--font-weight-medium);line-height:var(--line-height-normal);color:var(--color-text-secondary)}code,pre{font-family:var(--font-family-mono);font-size:.9em;line-height:var(--line-height-relaxed)}button{font-family:inherit;cursor:pointer}#root{width:100vw;height:100vh;overflow:hidden}@keyframes pulse{0%,to{opacity:1}50%{opacity:.6}}.react-flow__controls{background:var(--color-bg-surface)!important;border:1px solid var(--color-border-default)!important}.react-flow__controls-button{background:var(--color-bg-overlay)!important;border:none!important;border-bottom:1px solid var(--color-border-subtle)!important;color:var(--color-text-primary)!important;transition:var(--transition-all)!important;width:32px!important;height:32px!important}.react-flow__controls-button:hover{background:var(--color-primary-500)!important;color:#fff!important}.react-flow__controls-button svg{fill:currentColor!important;width:18px!important;height:18px!important}@media (prefers-reduced-motion: reduce){*{animation-duration:.01ms!important;animation-iteration-count:1!important;transition-duration:.01ms!important}}*::-webkit-scrollbar{width:10px;height:10px}*::-webkit-scrollbar-track{background:var(--color-bg-base);border-radius:var(--radius-sm, 4px)}*::-webkit-scrollbar-thumb{background:var(--color-bg-overlay);border-radius:var(--radius-sm, 4px);border:2px solid var(--color-bg-base)}*::-webkit-scrollbar-thumb:hover{background:var(--color-border-default)}*::-webkit-scrollbar-thumb:active{background:var(--color-border-strong)}*,div[style*="overflow: auto"],div[style*="overflow-y: auto"],div[style*="overflow-x: auto"],.settings-content,.publish-content{scrollbar-width:thin;scrollbar-color:var(--color-bg-overlay) var(--color-bg-base)}@keyframes pulse{0%,to{opacity:1}50%{opacity:.5}}
@@ -0,0 +1,13 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8" />
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
+ <title>🦆🐓 Flock 🐤🐧</title>
7
+ <script type="module" crossorigin src="/assets/index-DFRnI_mt.js"></script>
8
+ <link rel="stylesheet" crossorigin href="/assets/index-fPLNdmp1.css">
9
+ </head>
10
+ <body>
11
+ <div id="root"></div>
12
+ </body>
13
+ </html>
@@ -57,9 +57,9 @@ class WebSocketManager:
57
57
  self._heartbeat_task: asyncio.Task | None = None
58
58
  self._shutdown = False
59
59
 
60
- # Store streaming output events by agent_name for history (max 128000 per agent)
60
+ # Store streaming output events by agent_name for history (max 128344 per agent)
61
61
  self._streaming_history: dict[str, deque[StreamingOutputEvent]] = defaultdict(
62
- lambda: deque(maxlen=128000)
62
+ lambda: deque(maxlen=128344)
63
63
  )
64
64
 
65
65
  async def add_client(self, websocket: WebSocket) -> None:
@@ -242,19 +242,51 @@ class DSPyEngine(EngineComponent):
242
242
 
243
243
  try:
244
244
  if should_stream:
245
- (
246
- raw_result,
247
- _stream_final_display_data,
248
- ) = await self._execute_streaming(
249
- dspy_mod,
250
- program,
251
- signature,
252
- description=sys_desc,
253
- payload=execution_payload,
254
- agent=agent,
255
- ctx=ctx,
256
- pre_generated_artifact_id=pre_generated_artifact_id,
245
+ # Choose streaming method based on dashboard mode
246
+ is_dashboard = orchestrator and getattr(orchestrator, "is_dashboard", False)
247
+
248
+ # DEBUG: Log routing decision
249
+ logger.info(
250
+ f"[STREAMING ROUTER] agent={agent.name}, is_dashboard={is_dashboard}, orchestrator={orchestrator is not None}"
257
251
  )
252
+
253
+ if is_dashboard:
254
+ # Dashboard mode: WebSocket-only streaming (no Rich overhead)
255
+ # This eliminates the Rich Live context that causes deadlocks with MCP tools
256
+ logger.info(
257
+ f"[STREAMING ROUTER] Routing {agent.name} to WebSocket-only method (dashboard mode)"
258
+ )
259
+ (
260
+ raw_result,
261
+ _stream_final_display_data,
262
+ ) = await self._execute_streaming_websocket_only(
263
+ dspy_mod,
264
+ program,
265
+ signature,
266
+ description=sys_desc,
267
+ payload=execution_payload,
268
+ agent=agent,
269
+ ctx=ctx,
270
+ pre_generated_artifact_id=pre_generated_artifact_id,
271
+ )
272
+ else:
273
+ # CLI mode: Rich streaming with terminal display
274
+ logger.info(
275
+ f"[STREAMING ROUTER] Routing {agent.name} to Rich streaming method (CLI mode)"
276
+ )
277
+ (
278
+ raw_result,
279
+ _stream_final_display_data,
280
+ ) = await self._execute_streaming(
281
+ dspy_mod,
282
+ program,
283
+ signature,
284
+ description=sys_desc,
285
+ payload=execution_payload,
286
+ agent=agent,
287
+ ctx=ctx,
288
+ pre_generated_artifact_id=pre_generated_artifact_id,
289
+ )
258
290
  if not self.no_output and ctx:
259
291
  ctx.state["_flock_stream_live_active"] = True
260
292
  else:
@@ -503,6 +535,221 @@ class DSPyEngine(EngineComponent):
503
535
  # Handle old format: direct payload (backwards compatible)
504
536
  return program(description=description, input=payload, context=[])
505
537
 
538
+ async def _execute_streaming_websocket_only(
539
+ self,
540
+ dspy_mod,
541
+ program,
542
+ signature,
543
+ *,
544
+ description: str,
545
+ payload: dict[str, Any],
546
+ agent: Any,
547
+ ctx: Any = None,
548
+ pre_generated_artifact_id: Any = None,
549
+ ) -> tuple[Any, None]:
550
+ """Execute streaming for WebSocket only (no Rich display).
551
+
552
+ Optimized path for dashboard mode that skips all Rich formatting overhead.
553
+ Used when multiple agents stream in parallel to avoid terminal conflicts
554
+ and deadlocks with MCP tools.
555
+
556
+ This method eliminates the Rich Live context that can cause deadlocks when
557
+ combined with MCP tool execution and parallel agent streaming.
558
+ """
559
+ logger.info(f"Agent {agent.name}: Starting WebSocket-only streaming (dashboard mode)")
560
+
561
+ # Get WebSocketManager
562
+ ws_manager = None
563
+ if ctx:
564
+ orchestrator = getattr(ctx, "orchestrator", None)
565
+ if orchestrator:
566
+ collector = getattr(orchestrator, "_dashboard_collector", None)
567
+ if collector:
568
+ ws_manager = getattr(collector, "_websocket_manager", None)
569
+
570
+ if not ws_manager:
571
+ logger.warning(
572
+ f"Agent {agent.name}: No WebSocket manager, falling back to standard execution"
573
+ )
574
+ result = await self._execute_standard(
575
+ dspy_mod, program, description=description, payload=payload
576
+ )
577
+ return result, None
578
+
579
+ # Get artifact type name for WebSocket events
580
+ artifact_type_name = "output"
581
+ if hasattr(agent, "outputs") and agent.outputs:
582
+ artifact_type_name = agent.outputs[0].spec.type_name
583
+
584
+ # Prepare stream listeners
585
+ listeners = []
586
+ try:
587
+ streaming_mod = getattr(dspy_mod, "streaming", None)
588
+ if streaming_mod and hasattr(streaming_mod, "StreamListener"):
589
+ for name, field in signature.output_fields.items():
590
+ if field.annotation is str:
591
+ listeners.append(streaming_mod.StreamListener(signature_field_name=name))
592
+ except Exception:
593
+ listeners = []
594
+
595
+ # Create streaming task
596
+ streaming_task = dspy_mod.streamify(
597
+ program,
598
+ is_async_program=True,
599
+ stream_listeners=listeners if listeners else None,
600
+ )
601
+
602
+ # Execute with appropriate payload format
603
+ if isinstance(payload, dict) and "input" in payload:
604
+ stream_generator = streaming_task(
605
+ description=description,
606
+ input=payload["input"],
607
+ context=payload.get("context", []),
608
+ )
609
+ else:
610
+ stream_generator = streaming_task(description=description, input=payload, context=[])
611
+
612
+ # Process stream (WebSocket only, no Rich display)
613
+ final_result = None
614
+ stream_sequence = 0
615
+
616
+ # Track background WebSocket broadcast tasks to prevent garbage collection
617
+ # Using fire-and-forget pattern to avoid blocking DSPy's streaming loop
618
+ ws_broadcast_tasks: set[asyncio.Task] = set()
619
+
620
+ async for value in stream_generator:
621
+ try:
622
+ from dspy.streaming import StatusMessage, StreamResponse
623
+ from litellm import ModelResponseStream
624
+ except Exception:
625
+ StatusMessage = object # type: ignore
626
+ StreamResponse = object # type: ignore
627
+ ModelResponseStream = object # type: ignore
628
+
629
+ if isinstance(value, StatusMessage):
630
+ token = getattr(value, "message", "")
631
+ if token:
632
+ try:
633
+ event = StreamingOutputEvent(
634
+ correlation_id=str(ctx.correlation_id)
635
+ if ctx and ctx.correlation_id
636
+ else "",
637
+ agent_name=agent.name,
638
+ run_id=ctx.task_id if ctx else "",
639
+ output_type="log",
640
+ content=str(token + "\n"),
641
+ sequence=stream_sequence,
642
+ is_final=False,
643
+ artifact_id=str(pre_generated_artifact_id),
644
+ artifact_type=artifact_type_name,
645
+ )
646
+ # Fire-and-forget to avoid blocking DSPy's streaming loop
647
+ task = asyncio.create_task(ws_manager.broadcast(event))
648
+ ws_broadcast_tasks.add(task)
649
+ task.add_done_callback(ws_broadcast_tasks.discard)
650
+ stream_sequence += 1
651
+ except Exception as e:
652
+ logger.warning(f"Failed to emit streaming event: {e}")
653
+
654
+ elif isinstance(value, StreamResponse):
655
+ token = getattr(value, "chunk", None)
656
+ if token:
657
+ try:
658
+ event = StreamingOutputEvent(
659
+ correlation_id=str(ctx.correlation_id)
660
+ if ctx and ctx.correlation_id
661
+ else "",
662
+ agent_name=agent.name,
663
+ run_id=ctx.task_id if ctx else "",
664
+ output_type="llm_token",
665
+ content=str(token),
666
+ sequence=stream_sequence,
667
+ is_final=False,
668
+ artifact_id=str(pre_generated_artifact_id),
669
+ artifact_type=artifact_type_name,
670
+ )
671
+ # Fire-and-forget to avoid blocking DSPy's streaming loop
672
+ task = asyncio.create_task(ws_manager.broadcast(event))
673
+ ws_broadcast_tasks.add(task)
674
+ task.add_done_callback(ws_broadcast_tasks.discard)
675
+ stream_sequence += 1
676
+ except Exception as e:
677
+ logger.warning(f"Failed to emit streaming event: {e}")
678
+
679
+ elif isinstance(value, ModelResponseStream):
680
+ chunk = value
681
+ token = chunk.choices[0].delta.content or ""
682
+ if token:
683
+ try:
684
+ event = StreamingOutputEvent(
685
+ correlation_id=str(ctx.correlation_id)
686
+ if ctx and ctx.correlation_id
687
+ else "",
688
+ agent_name=agent.name,
689
+ run_id=ctx.task_id if ctx else "",
690
+ output_type="llm_token",
691
+ content=str(token),
692
+ sequence=stream_sequence,
693
+ is_final=False,
694
+ artifact_id=str(pre_generated_artifact_id),
695
+ artifact_type=artifact_type_name,
696
+ )
697
+ # Fire-and-forget to avoid blocking DSPy's streaming loop
698
+ task = asyncio.create_task(ws_manager.broadcast(event))
699
+ ws_broadcast_tasks.add(task)
700
+ task.add_done_callback(ws_broadcast_tasks.discard)
701
+ stream_sequence += 1
702
+ except Exception as e:
703
+ logger.warning(f"Failed to emit streaming event: {e}")
704
+
705
+ elif isinstance(value, dspy_mod.Prediction):
706
+ final_result = value
707
+ # Send final events
708
+ try:
709
+ event = StreamingOutputEvent(
710
+ correlation_id=str(ctx.correlation_id)
711
+ if ctx and ctx.correlation_id
712
+ else "",
713
+ agent_name=agent.name,
714
+ run_id=ctx.task_id if ctx else "",
715
+ output_type="log",
716
+ content=f"\nAmount of output tokens: {stream_sequence}",
717
+ sequence=stream_sequence,
718
+ is_final=True,
719
+ artifact_id=str(pre_generated_artifact_id),
720
+ artifact_type=artifact_type_name,
721
+ )
722
+ # Fire-and-forget to avoid blocking DSPy's streaming loop
723
+ task = asyncio.create_task(ws_manager.broadcast(event))
724
+ ws_broadcast_tasks.add(task)
725
+ task.add_done_callback(ws_broadcast_tasks.discard)
726
+
727
+ event = StreamingOutputEvent(
728
+ correlation_id=str(ctx.correlation_id)
729
+ if ctx and ctx.correlation_id
730
+ else "",
731
+ agent_name=agent.name,
732
+ run_id=ctx.task_id if ctx else "",
733
+ output_type="log",
734
+ content="--- End of output ---",
735
+ sequence=stream_sequence + 1,
736
+ is_final=True,
737
+ artifact_id=str(pre_generated_artifact_id),
738
+ artifact_type=artifact_type_name,
739
+ )
740
+ # Fire-and-forget to avoid blocking DSPy's streaming loop
741
+ task = asyncio.create_task(ws_manager.broadcast(event))
742
+ ws_broadcast_tasks.add(task)
743
+ task.add_done_callback(ws_broadcast_tasks.discard)
744
+ except Exception as e:
745
+ logger.warning(f"Failed to emit final streaming event: {e}")
746
+
747
+ if final_result is None:
748
+ raise RuntimeError(f"Agent {agent.name}: Streaming did not yield a final prediction")
749
+
750
+ logger.info(f"Agent {agent.name}: WebSocket streaming completed ({stream_sequence} tokens)")
751
+ return final_result, None
752
+
506
753
  async def _execute_streaming(
507
754
  self,
508
755
  dspy_mod,
@@ -571,12 +818,12 @@ class DSPyEngine(EngineComponent):
571
818
  # Use the pre-generated artifact ID that was created before execution started
572
819
  display_data["id"] = str(pre_generated_artifact_id)
573
820
 
574
- # Get the output type from agent configuration
575
- output_type = "output"
821
+ # Get the artifact type name from agent configuration
822
+ artifact_type_name = "output"
576
823
  if hasattr(agent, "outputs") and agent.outputs:
577
- output_type = agent.outputs[0].spec.type_name
824
+ artifact_type_name = agent.outputs[0].spec.type_name
578
825
 
579
- display_data["type"] = output_type
826
+ display_data["type"] = artifact_type_name
580
827
  display_data["payload"] = OrderedDict()
581
828
 
582
829
  # Add output fields to payload section
@@ -660,6 +907,10 @@ class DSPyEngine(EngineComponent):
660
907
  content=str(token + "\n"),
661
908
  sequence=stream_sequence,
662
909
  is_final=False,
910
+ artifact_id=str(
911
+ pre_generated_artifact_id
912
+ ), # Phase 6: Track artifact for message streaming
913
+ artifact_type=artifact_type_name, # Phase 6: Artifact type name
663
914
  )
664
915
  # Use create_task to avoid blocking the streaming loop
665
916
  task = asyncio.create_task(ws_manager.broadcast(event))
@@ -704,6 +955,10 @@ class DSPyEngine(EngineComponent):
704
955
  content=str(token),
705
956
  sequence=stream_sequence,
706
957
  is_final=False,
958
+ artifact_id=str(
959
+ pre_generated_artifact_id
960
+ ), # Phase 6: Track artifact for message streaming
961
+ artifact_type=artifact_type_name, # Phase 6: Artifact type name
707
962
  )
708
963
  # Use create_task to avoid blocking the streaming loop
709
964
  task = asyncio.create_task(ws_manager.broadcast(event))
@@ -722,9 +977,6 @@ class DSPyEngine(EngineComponent):
722
977
  token = chunk.choices[0].delta.content or ""
723
978
  signature_field = getattr(value, "signature_field_name", None)
724
979
 
725
- # Determine output type based on signature field
726
- output_type = "llm_token" # if signature_field and signature_field != "description" else "log"
727
-
728
980
  if signature_field and signature_field != "description":
729
981
  # Update payload section - accumulate in buffer
730
982
  buffer_key = f"_stream_{signature_field}"
@@ -747,10 +999,16 @@ class DSPyEngine(EngineComponent):
747
999
  else "",
748
1000
  agent_name=agent.name,
749
1001
  run_id=ctx.task_id if ctx else "",
750
- output_type=output_type,
1002
+ output_type="llm_token",
751
1003
  content=str(token),
752
1004
  sequence=stream_sequence,
753
1005
  is_final=False,
1006
+ artifact_id=str(
1007
+ pre_generated_artifact_id
1008
+ ), # Phase 6: Track artifact for message streaming
1009
+ artifact_type=display_data[
1010
+ "type"
1011
+ ], # Phase 6: Artifact type name from display_data
754
1012
  )
755
1013
  # Use create_task to avoid blocking the streaming loop
756
1014
  task = asyncio.create_task(ws_manager.broadcast(event))
@@ -780,6 +1038,10 @@ class DSPyEngine(EngineComponent):
780
1038
  content="\nAmount of output tokens: " + str(stream_sequence),
781
1039
  sequence=stream_sequence,
782
1040
  is_final=True, # Mark as final
1041
+ artifact_id=str(
1042
+ pre_generated_artifact_id
1043
+ ), # Phase 6: Track artifact for message streaming
1044
+ artifact_type=display_data["type"], # Phase 6: Artifact type name
783
1045
  )
784
1046
  # Use create_task to avoid blocking the streaming loop
785
1047
  task = asyncio.create_task(ws_manager.broadcast(event))
@@ -795,6 +1057,10 @@ class DSPyEngine(EngineComponent):
795
1057
  content="--- End of output ---",
796
1058
  sequence=stream_sequence,
797
1059
  is_final=True, # Mark as final
1060
+ artifact_id=str(
1061
+ pre_generated_artifact_id
1062
+ ), # Phase 6: Track artifact for message streaming
1063
+ artifact_type=display_data["type"], # Phase 6: Artifact type name
798
1064
  )
799
1065
  # Use create_task to avoid blocking the streaming loop
800
1066
  task = asyncio.create_task(ws_manager.broadcast(event))
@@ -911,3 +1177,11 @@ __all__ = ["DSPyEngine"]
911
1177
 
912
1178
  # Apply the Rich Live patch when this module is imported
913
1179
  _apply_live_patch_on_import()
1180
+
1181
+ # Apply the DSPy streaming patch to fix deadlocks with MCP tools
1182
+ try:
1183
+ from flock.patches.dspy_streaming_patch import apply_patch as apply_dspy_streaming_patch
1184
+
1185
+ apply_dspy_streaming_patch()
1186
+ except Exception:
1187
+ pass # Silently ignore if patch fails to apply
flock/frontend/README.md CHANGED
@@ -149,7 +149,7 @@ Launch the module via the context menu (or `Add Module → Historical Blackboard
149
149
 
150
150
  - **Node.js**: Version 18 or higher
151
151
  - **Package Manager**: npm (included with Node.js) or yarn
152
- - **Flock Flow Backend**: Running orchestrator instance (typically on port 8000)
152
+ - **Flock Flow Backend**: Running orchestrator instance (typically on port 8344)
153
153
 
154
154
  ### Installation
155
155
 
@@ -205,11 +205,11 @@ The dashboard can be configured via environment variables:
205
205
 
206
206
  ```bash
207
207
  # .env file
208
- VITE_WS_URL=ws://localhost:8000/ws
209
- VITE_API_URL=http://localhost:8000/api
208
+ VITE_WS_URL=ws://localhost:8344/ws
209
+ VITE_API_URL=http://localhost:8344/api
210
210
  ```
211
211
 
212
- If not specified, defaults to `localhost:8000`.
212
+ If not specified, defaults to `localhost:8344`.
213
213
 
214
214
  ## Design System
215
215
 
@@ -596,7 +596,7 @@ npm run type-check
596
596
 
597
597
  **Solutions**:
598
598
  1. Check browser console for errors (F12)
599
- 2. Verify backend is running on port 8000
599
+ 2. Verify backend is running on port 8344
600
600
  3. Check WebSocket connection status in UI
601
601
  4. Clear IndexedDB: Open DevTools → Application → IndexedDB → Delete
602
602
  5. Clear localStorage: `localStorage.clear()` in console
@@ -606,7 +606,7 @@ npm run type-check
606
606
  **Symptom**: "Disconnected" status indicator
607
607
 
608
608
  **Solutions**:
609
- 1. Verify backend WebSocket endpoint is accessible: `ws://localhost:8000/ws`
609
+ 1. Verify backend WebSocket endpoint is accessible: `ws://localhost:8344/ws`
610
610
  2. Check for CORS issues in browser console
611
611
  3. Check network tab for WebSocket connection attempts
612
612
  4. Restart the backend server