flock-core 0.5.0b70__py3-none-any.whl → 0.5.0b75__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 (62) 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/graph.py +156 -0
  10. flock/dashboard/service.py +175 -14
  11. flock/dashboard/static_v2/assets/index-DFRnI_mt.js +111 -0
  12. flock/dashboard/static_v2/assets/index-fPLNdmp1.css +1 -0
  13. flock/dashboard/static_v2/index.html +13 -0
  14. flock/dashboard/websocket.py +2 -2
  15. flock/engines/dspy_engine.py +28 -9
  16. flock/frontend/README.md +6 -6
  17. flock/frontend/src/App.tsx +23 -31
  18. flock/frontend/src/__tests__/integration/graph-snapshot.test.tsx +647 -0
  19. flock/frontend/src/components/details/DetailWindowContainer.tsx +13 -17
  20. flock/frontend/src/components/details/MessageDetailWindow.tsx +439 -0
  21. flock/frontend/src/components/details/MessageHistoryTab.tsx +128 -53
  22. flock/frontend/src/components/details/RunStatusTab.tsx +79 -38
  23. flock/frontend/src/components/graph/AgentNode.test.tsx +3 -1
  24. flock/frontend/src/components/graph/AgentNode.tsx +8 -6
  25. flock/frontend/src/components/graph/GraphCanvas.tsx +13 -8
  26. flock/frontend/src/components/graph/MessageNode.test.tsx +3 -1
  27. flock/frontend/src/components/graph/MessageNode.tsx +16 -3
  28. flock/frontend/src/components/layout/DashboardLayout.tsx +12 -9
  29. flock/frontend/src/components/modules/HistoricalArtifactsModule.tsx +4 -14
  30. flock/frontend/src/components/modules/ModuleRegistry.ts +5 -3
  31. flock/frontend/src/hooks/useModules.ts +12 -4
  32. flock/frontend/src/hooks/usePersistence.ts +5 -3
  33. flock/frontend/src/services/api.ts +3 -19
  34. flock/frontend/src/services/graphService.test.ts +330 -0
  35. flock/frontend/src/services/graphService.ts +75 -0
  36. flock/frontend/src/services/websocket.ts +104 -268
  37. flock/frontend/src/store/filterStore.test.ts +89 -1
  38. flock/frontend/src/store/filterStore.ts +38 -16
  39. flock/frontend/src/store/graphStore.test.ts +538 -173
  40. flock/frontend/src/store/graphStore.ts +374 -465
  41. flock/frontend/src/store/moduleStore.ts +51 -33
  42. flock/frontend/src/store/uiStore.ts +23 -11
  43. flock/frontend/src/types/graph.ts +77 -44
  44. flock/frontend/src/utils/mockData.ts +16 -3
  45. flock/frontend/vite.config.ts +2 -2
  46. flock/orchestrator.py +24 -6
  47. flock/service.py +2 -2
  48. flock/store.py +169 -4
  49. flock/themes/darkmatrix.toml +2 -2
  50. flock/themes/deep.toml +2 -2
  51. flock/themes/neopolitan.toml +4 -4
  52. {flock_core-0.5.0b70.dist-info → flock_core-0.5.0b75.dist-info}/METADATA +1 -1
  53. {flock_core-0.5.0b70.dist-info → flock_core-0.5.0b75.dist-info}/RECORD +56 -53
  54. flock/frontend/src/__tests__/e2e/critical-scenarios.test.tsx +0 -586
  55. flock/frontend/src/__tests__/integration/filtering-e2e.test.tsx +0 -391
  56. flock/frontend/src/__tests__/integration/graph-rendering.test.tsx +0 -640
  57. flock/frontend/src/services/websocket.test.ts +0 -595
  58. flock/frontend/src/utils/transforms.test.ts +0 -860
  59. flock/frontend/src/utils/transforms.ts +0 -323
  60. {flock_core-0.5.0b70.dist-info → flock_core-0.5.0b75.dist-info}/WHEEL +0 -0
  61. {flock_core-0.5.0b70.dist-info → flock_core-0.5.0b75.dist-info}/entry_points.txt +0 -0
  62. {flock_core-0.5.0b70.dist-info → flock_core-0.5.0b75.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:
@@ -571,12 +571,12 @@ class DSPyEngine(EngineComponent):
571
571
  # Use the pre-generated artifact ID that was created before execution started
572
572
  display_data["id"] = str(pre_generated_artifact_id)
573
573
 
574
- # Get the output type from agent configuration
575
- output_type = "output"
574
+ # Get the artifact type name from agent configuration
575
+ artifact_type_name = "output"
576
576
  if hasattr(agent, "outputs") and agent.outputs:
577
- output_type = agent.outputs[0].spec.type_name
577
+ artifact_type_name = agent.outputs[0].spec.type_name
578
578
 
579
- display_data["type"] = output_type
579
+ display_data["type"] = artifact_type_name
580
580
  display_data["payload"] = OrderedDict()
581
581
 
582
582
  # Add output fields to payload section
@@ -660,6 +660,10 @@ class DSPyEngine(EngineComponent):
660
660
  content=str(token + "\n"),
661
661
  sequence=stream_sequence,
662
662
  is_final=False,
663
+ artifact_id=str(
664
+ pre_generated_artifact_id
665
+ ), # Phase 6: Track artifact for message streaming
666
+ artifact_type=artifact_type_name, # Phase 6: Artifact type name
663
667
  )
664
668
  # Use create_task to avoid blocking the streaming loop
665
669
  task = asyncio.create_task(ws_manager.broadcast(event))
@@ -669,7 +673,7 @@ class DSPyEngine(EngineComponent):
669
673
  except Exception as e:
670
674
  logger.warning(f"Failed to emit streaming event: {e}")
671
675
  else:
672
- logger.exception("NO WS_MANAGER PRESENT!!!!")
676
+ logger.debug("No WebSocket manager present for streaming event.")
673
677
 
674
678
  if formatter is not None:
675
679
  _refresh_panel()
@@ -704,6 +708,10 @@ class DSPyEngine(EngineComponent):
704
708
  content=str(token),
705
709
  sequence=stream_sequence,
706
710
  is_final=False,
711
+ artifact_id=str(
712
+ pre_generated_artifact_id
713
+ ), # Phase 6: Track artifact for message streaming
714
+ artifact_type=artifact_type_name, # Phase 6: Artifact type name
707
715
  )
708
716
  # Use create_task to avoid blocking the streaming loop
709
717
  task = asyncio.create_task(ws_manager.broadcast(event))
@@ -722,9 +730,6 @@ class DSPyEngine(EngineComponent):
722
730
  token = chunk.choices[0].delta.content or ""
723
731
  signature_field = getattr(value, "signature_field_name", None)
724
732
 
725
- # Determine output type based on signature field
726
- output_type = "llm_token" # if signature_field and signature_field != "description" else "log"
727
-
728
733
  if signature_field and signature_field != "description":
729
734
  # Update payload section - accumulate in buffer
730
735
  buffer_key = f"_stream_{signature_field}"
@@ -747,10 +752,16 @@ class DSPyEngine(EngineComponent):
747
752
  else "",
748
753
  agent_name=agent.name,
749
754
  run_id=ctx.task_id if ctx else "",
750
- output_type=output_type,
755
+ output_type="llm_token",
751
756
  content=str(token),
752
757
  sequence=stream_sequence,
753
758
  is_final=False,
759
+ artifact_id=str(
760
+ pre_generated_artifact_id
761
+ ), # Phase 6: Track artifact for message streaming
762
+ artifact_type=display_data[
763
+ "type"
764
+ ], # Phase 6: Artifact type name from display_data
754
765
  )
755
766
  # Use create_task to avoid blocking the streaming loop
756
767
  task = asyncio.create_task(ws_manager.broadcast(event))
@@ -780,6 +791,10 @@ class DSPyEngine(EngineComponent):
780
791
  content="\nAmount of output tokens: " + str(stream_sequence),
781
792
  sequence=stream_sequence,
782
793
  is_final=True, # Mark as final
794
+ artifact_id=str(
795
+ pre_generated_artifact_id
796
+ ), # Phase 6: Track artifact for message streaming
797
+ artifact_type=display_data["type"], # Phase 6: Artifact type name
783
798
  )
784
799
  # Use create_task to avoid blocking the streaming loop
785
800
  task = asyncio.create_task(ws_manager.broadcast(event))
@@ -795,6 +810,10 @@ class DSPyEngine(EngineComponent):
795
810
  content="--- End of output ---",
796
811
  sequence=stream_sequence,
797
812
  is_final=True, # Mark as final
813
+ artifact_id=str(
814
+ pre_generated_artifact_id
815
+ ), # Phase 6: Track artifact for message streaming
816
+ artifact_type=display_data["type"], # Phase 6: Artifact type name
798
817
  )
799
818
  # Use create_task to avoid blocking the streaming loop
800
819
  task = asyncio.create_task(ws_manager.broadcast(event))
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
@@ -5,11 +5,10 @@ import { measureRenderTime } from './utils/performance';
5
5
  import { initializeWebSocket } from './services/websocket';
6
6
  import { registerModules } from './components/modules/registerModules';
7
7
  import { useKeyboardShortcuts } from './hooks/useKeyboardShortcuts';
8
- import { fetchRegisteredAgents, fetchArtifactSummary, fetchArtifacts } from './services/api';
8
+ import { fetchArtifactSummary, fetchArtifacts } from './services/api';
9
9
  import { useGraphStore } from './store/graphStore';
10
10
  import { useUIStore } from './store/uiStore';
11
11
  import { useFilterStore } from './store/filterStore';
12
- import { mapArtifactToMessage } from './utils/artifacts';
13
12
  import { indexedDBService } from './services/indexeddb';
14
13
 
15
14
  // Register modules once at module load time
@@ -38,9 +37,10 @@ const App: React.FC = () => {
38
37
  await indexedDBService.initialize();
39
38
 
40
39
  const filterStore = useFilterStore.getState();
41
- const graphStore = useGraphStore.getState();
42
- const uiStore = useUIStore.getState();
43
40
 
41
+ // UI Optimization Migration (Phase 2/4 - Spec 002): Backend-driven architecture
42
+ // Fetch artifact summary to populate filter facets
43
+ // Note: Node positions are now loaded automatically in generateAgentViewGraph/generateBlackboardViewGraph
44
44
  const summary = await fetchArtifactSummary();
45
45
  filterStore.setSummary(summary);
46
46
  filterStore.updateAvailableFacets({
@@ -50,17 +50,9 @@ const App: React.FC = () => {
50
50
  visibilities: Object.keys(summary.by_visibility),
51
51
  });
52
52
 
53
+ // Fetch correlation IDs for filter dropdown
53
54
  const artifactResponse = await fetchArtifacts({ limit: 200, embedMeta: true });
54
- const messages = artifactResponse.items.map(mapArtifactToMessage);
55
- if (messages.length > 0) {
56
- graphStore.batchUpdate({ messages });
57
- if (uiStore.mode === 'blackboard') {
58
- graphStore.generateBlackboardViewGraph();
59
- } else {
60
- graphStore.generateAgentViewGraph();
61
- }
62
- graphStore.applyFilters();
63
-
55
+ if (artifactResponse.items.length > 0) {
64
56
  const correlationMetadata = new Map<string, { correlation_id: string; first_seen: number; artifact_count: number; run_count: number }>();
65
57
  artifactResponse.items.forEach((item) => {
66
58
  if (!item.correlation_id) return;
@@ -82,44 +74,44 @@ const App: React.FC = () => {
82
74
  filterStore.updateAvailableCorrelationIds(Array.from(correlationMetadata.values()));
83
75
  }
84
76
  }
77
+
78
+ // Generate initial graph view from backend snapshot
79
+ // (GraphCanvas useEffect will handle initial render based on mode)
80
+ // No need to manually trigger here - happens in GraphCanvas mount
85
81
  } catch (error) {
86
82
  console.error('[App] Failed to load historical artifacts:', error);
87
83
  }
88
84
  };
89
85
 
90
- // Load registered agents from orchestrator
91
- // This pre-populates the graph with all agent nodes before any events occur
92
- const loadInitialAgents = async () => {
86
+ // UI Optimization Migration (Phase 2/4 - Spec 002): Simplified initial graph load
87
+ // Backend snapshot includes all agents + artifacts + edges in a single call
88
+ const loadInitialGraph = async () => {
93
89
  try {
94
- console.log('[App] Fetching registered agents...');
95
- const agents = await fetchRegisteredAgents();
96
- console.log(`[App] Loaded ${agents.length} registered agents`);
97
-
90
+ console.log('[App] Loading initial graph from backend snapshot...');
98
91
  const graphStore = useGraphStore.getState();
99
92
  const uiStore = useUIStore.getState();
100
93
 
101
- // Add all agents to the store
102
- agents.forEach(agent => graphStore.addAgent(agent));
103
-
104
- // Generate initial graph layout based on current view mode
94
+ // Fetch complete graph snapshot from backend (includes agents + artifacts + edges)
105
95
  if (uiStore.mode === 'agent') {
106
- graphStore.generateAgentViewGraph();
96
+ await graphStore.generateAgentViewGraph();
107
97
  } else {
108
- graphStore.generateBlackboardViewGraph();
98
+ await graphStore.generateBlackboardViewGraph();
109
99
  }
100
+
101
+ console.log('[App] Initial graph loaded from backend');
110
102
  } catch (error) {
111
- console.error('[App] Failed to load registered agents:', error);
112
- // Graceful degradation: agents will appear when they activate via WebSocket
103
+ console.error('[App] Failed to load initial graph:', error);
104
+ // Graceful degradation: graph will populate as WebSocket events arrive
113
105
  }
114
106
  };
115
107
 
116
- const wsUrl = import.meta.env.VITE_WS_URL || 'ws://localhost:8000/ws';
108
+ const wsUrl = import.meta.env.VITE_WS_URL || 'ws://localhost:8344/ws';
117
109
  const wsClient = initializeWebSocket(wsUrl);
118
110
  let cancelled = false;
119
111
 
120
112
  const bootstrap = async () => {
121
113
  await loadHistoricalData();
122
- await loadInitialAgents();
114
+ await loadInitialGraph();
123
115
 
124
116
  if (!cancelled) {
125
117
  wsClient.connect();