@agentic-surfaces/server 0.1.4

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.
@@ -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;touch-action:none}.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))}*,:before,:after{--tw-border-spacing-x: 0;--tw-border-spacing-y: 0;--tw-translate-x: 0;--tw-translate-y: 0;--tw-rotate: 0;--tw-skew-x: 0;--tw-skew-y: 0;--tw-scale-x: 1;--tw-scale-y: 1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness: proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width: 0px;--tw-ring-offset-color: #fff;--tw-ring-color: rgb(59 130 246 / .5);--tw-ring-offset-shadow: 0 0 #0000;--tw-ring-shadow: 0 0 #0000;--tw-shadow: 0 0 #0000;--tw-shadow-colored: 0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: ;--tw-contain-size: ;--tw-contain-layout: ;--tw-contain-paint: ;--tw-contain-style: }::backdrop{--tw-border-spacing-x: 0;--tw-border-spacing-y: 0;--tw-translate-x: 0;--tw-translate-y: 0;--tw-rotate: 0;--tw-skew-x: 0;--tw-skew-y: 0;--tw-scale-x: 1;--tw-scale-y: 1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness: proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width: 0px;--tw-ring-offset-color: #fff;--tw-ring-color: rgb(59 130 246 / .5);--tw-ring-offset-shadow: 0 0 #0000;--tw-ring-shadow: 0 0 #0000;--tw-shadow: 0 0 #0000;--tw-shadow-colored: 0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: ;--tw-contain-size: ;--tw-contain-layout: ;--tw-contain-paint: ;--tw-contain-style: }*,:before,:after{box-sizing:border-box;border-width:0;border-style:solid;border-color:#e5e7eb}:before,:after{--tw-content: ""}html,:host{line-height:1.5;-webkit-text-size-adjust:100%;-moz-tab-size:4;-o-tab-size:4;tab-size:4;font-family:Inter,system-ui,sans-serif;font-feature-settings:normal;font-variation-settings:normal;-webkit-tap-highlight-color:transparent}body{margin:0;line-height:inherit}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,samp,pre{font-family:JetBrains Mono,monospace;font-feature-settings:normal;font-variation-settings:normal;font-size:1em}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}button,input,optgroup,select,textarea{font-family:inherit;font-feature-settings:inherit;font-variation-settings:inherit;font-size:100%;font-weight:inherit;line-height:inherit;letter-spacing:inherit;color:inherit;margin:0;padding:0}button,select{text-transform:none}button,input:where([type=button]),input:where([type=reset]),input:where([type=submit]){-webkit-appearance:button;background-color:transparent;background-image:none}:-moz-focusring{outline:auto}:-moz-ui-invalid{box-shadow:none}progress{vertical-align:baseline}::-webkit-inner-spin-button,::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}summary{display:list-item}blockquote,dl,dd,h1,h2,h3,h4,h5,h6,hr,figure,p,pre{margin:0}fieldset{margin:0;padding:0}legend{padding:0}ol,ul,menu{list-style:none;margin:0;padding:0}dialog{padding:0}textarea{resize:vertical}input::-moz-placeholder,textarea::-moz-placeholder{opacity:1;color:#9ca3af}input::placeholder,textarea::placeholder{opacity:1;color:#9ca3af}button,[role=button]{cursor:pointer}:disabled{cursor:default}img,svg,video,canvas,audio,iframe,embed,object{display:block;vertical-align:middle}img,video{max-width:100%;height:auto}[hidden]:where(:not([hidden=until-found])){display:none}.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border-width:0}.pointer-events-none{pointer-events:none}.static{position:static}.fixed{position:fixed}.absolute{position:absolute}.relative{position:relative}.inset-0{top:0;right:0;bottom:0;left:0}.inset-y-0{top:0;bottom:0}.bottom-3{bottom:.75rem}.left-0{left:0}.right-0{right:0}.right-14{right:3.5rem}.right-4{right:1rem}.top-4{top:1rem}.z-10{z-index:10}.z-50{z-index:50}.ml-auto{margin-left:auto}.mt-0\.5{margin-top:.125rem}.mt-1{margin-top:.25rem}.mt-auto{margin-top:auto}.flex{display:flex}.inline-flex{display:inline-flex}.grid{display:grid}.size-1\.5{width:.375rem;height:.375rem}.size-5{width:1.25rem;height:1.25rem}.h-1{height:.25rem}.h-12{height:3rem}.h-2\.5{height:.625rem}.h-4{height:1rem}.h-64{height:16rem}.h-7{height:1.75rem}.h-8{height:2rem}.h-\[1px\]{height:1px}.h-full{height:100%}.h-screen{height:100vh}.min-h-0{min-height:0px}.w-2\.5{width:.625rem}.w-4{width:1rem}.w-60{width:15rem}.w-8{width:2rem}.w-80{width:20rem}.w-\[1px\]{width:1px}.w-\[520px\]{width:520px}.w-full{width:100%}.w-screen{width:100vw}.min-w-0{min-width:0px}.max-w-3xl{max-width:48rem}.max-w-\[90vw\]{max-width:90vw}.flex-1{flex:1 1 0%}.flex-shrink-0,.shrink-0{flex-shrink:0}.transform{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.cursor-pointer{cursor:pointer}.touch-none{touch-action:none}.select-none{-webkit-user-select:none;-moz-user-select:none;user-select:none}.resize-y{resize:vertical}.grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.flex-col{flex-direction:column}.items-center{align-items:center}.justify-end{justify-content:flex-end}.justify-center{justify-content:center}.justify-between{justify-content:space-between}.gap-1\.5{gap:.375rem}.gap-2{gap:.5rem}.gap-3{gap:.75rem}.space-y-0\.5>:not([hidden])~:not([hidden]){--tw-space-y-reverse: 0;margin-top:calc(.125rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.125rem * var(--tw-space-y-reverse))}.space-y-1\.5>:not([hidden])~:not([hidden]){--tw-space-y-reverse: 0;margin-top:calc(.375rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.375rem * var(--tw-space-y-reverse))}.space-y-2>:not([hidden])~:not([hidden]){--tw-space-y-reverse: 0;margin-top:calc(.5rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.5rem * var(--tw-space-y-reverse))}.space-y-4>:not([hidden])~:not([hidden]){--tw-space-y-reverse: 0;margin-top:calc(1rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(1rem * var(--tw-space-y-reverse))}.overflow-hidden{overflow:hidden}.overflow-x-auto{overflow-x:auto}.overflow-y-auto{overflow-y:auto}.whitespace-pre-wrap{white-space:pre-wrap}.break-all{word-break:break-all}.rounded{border-radius:.25rem}.rounded-\[inherit\]{border-radius:inherit}.rounded-full{border-radius:9999px}.rounded-lg{border-radius:.5rem}.rounded-md{border-radius:.375rem}.rounded-sm{border-radius:.25rem}.border{border-width:1px}.border-2{border-width:2px}.border-b{border-bottom-width:1px}.border-l{border-left-width:1px}.border-r{border-right-width:1px}.border-t{border-top-width:1px}.border-dashed{border-style:dashed}.border-agent\/40{border-color:#5048e566}.border-border{--tw-border-opacity: 1;border-color:hsl(240 5.9% 90% / var(--tw-border-opacity, 1))}.border-primary{--tw-border-opacity: 1;border-color:hsl(240 10% 3.9% / var(--tw-border-opacity, 1))}.border-l-transparent{border-left-color:transparent}.border-t-transparent{border-top-color:transparent}.\!bg-agent\/50{background-color:#5048e580!important}.\!bg-mutedfg\/50{background-color:#71717a80!important}.bg-agent{--tw-bg-opacity: 1;background-color:hsl(243 75% 59% / var(--tw-bg-opacity, 1))}.bg-agent\/10{background-color:#5048e51a}.bg-agentbg{--tw-bg-opacity: 1;background-color:hsl(243 100% 98% / var(--tw-bg-opacity, 1))}.bg-bg{--tw-bg-opacity: 1;background-color:hsl(0 0% 100% / var(--tw-bg-opacity, 1))}.bg-bg\/70{background-color:#ffffffb3}.bg-bg\/80{background-color:#fffc}.bg-black\/20{background-color:#0003}.bg-border{--tw-bg-opacity: 1;background-color:hsl(240 5.9% 90% / var(--tw-bg-opacity, 1))}.bg-card{--tw-bg-opacity: 1;background-color:hsl(0 0% 100% / var(--tw-bg-opacity, 1))}.bg-fail{--tw-bg-opacity: 1;background-color:hsl(0 72% 51% / var(--tw-bg-opacity, 1))}.bg-fg{--tw-bg-opacity: 1;background-color:hsl(240 10% 3.9% / var(--tw-bg-opacity, 1))}.bg-muted{--tw-bg-opacity: 1;background-color:hsl(240 4.8% 95.9% / var(--tw-bg-opacity, 1))}.bg-mutedfg\/30{background-color:#71717a4d}.bg-ok{--tw-bg-opacity: 1;background-color:hsl(142 71% 45% / var(--tw-bg-opacity, 1))}.bg-primary{--tw-bg-opacity: 1;background-color:hsl(240 10% 3.9% / var(--tw-bg-opacity, 1))}.bg-run{--tw-bg-opacity: 1;background-color:hsl(38 92% 50% / var(--tw-bg-opacity, 1))}.p-2{padding:.5rem}.p-2\.5{padding:.625rem}.p-3{padding:.75rem}.p-4{padding:1rem}.p-\[1px\]{padding:1px}.px-1{padding-left:.25rem;padding-right:.25rem}.px-1\.5{padding-left:.375rem;padding-right:.375rem}.px-2{padding-left:.5rem;padding-right:.5rem}.px-2\.5{padding-left:.625rem;padding-right:.625rem}.px-3{padding-left:.75rem;padding-right:.75rem}.px-4{padding-left:1rem;padding-right:1rem}.py-0\.5{padding-top:.125rem;padding-bottom:.125rem}.py-1{padding-top:.25rem;padding-bottom:.25rem}.py-1\.5{padding-top:.375rem;padding-bottom:.375rem}.py-2{padding-top:.5rem;padding-bottom:.5rem}.py-4{padding-top:1rem;padding-bottom:1rem}.pb-1{padding-bottom:.25rem}.pt-0{padding-top:0}.pt-3{padding-top:.75rem}.pt-5{padding-top:1.25rem}.text-left{text-align:left}.text-center{text-align:center}.font-mono{font-family:JetBrains Mono,monospace}.font-sans{font-family:Inter,system-ui,sans-serif}.text-\[10px\]{font-size:10px}.text-\[11px\]{font-size:11px}.text-\[12px\]{font-size:12px}.text-\[13px\]{font-size:13px}.text-\[9px\]{font-size:9px}.text-lg{font-size:1.125rem;line-height:1.75rem}.text-sm{font-size:.875rem;line-height:1.25rem}.text-xs{font-size:.75rem;line-height:1rem}.font-medium{font-weight:500}.font-semibold{font-weight:600}.uppercase{text-transform:uppercase}.leading-none{line-height:1}.leading-relaxed{line-height:1.625}.tracking-tight{letter-spacing:-.025em}.tracking-wide{letter-spacing:.025em}.tracking-wider{letter-spacing:.05em}.text-agent{--tw-text-opacity: 1;color:hsl(243 75% 59% / var(--tw-text-opacity, 1))}.text-agent\/60{color:#5048e599}.text-agent\/70{color:#5048e5b3}.text-bg{--tw-text-opacity: 1;color:hsl(0 0% 100% / var(--tw-text-opacity, 1))}.text-fail{--tw-text-opacity: 1;color:hsl(0 72% 51% / var(--tw-text-opacity, 1))}.text-fg{--tw-text-opacity: 1;color:hsl(240 10% 3.9% / var(--tw-text-opacity, 1))}.text-mutedfg{--tw-text-opacity: 1;color:hsl(240 3.8% 46.1% / var(--tw-text-opacity, 1))}.text-ok{--tw-text-opacity: 1;color:hsl(142 71% 45% / var(--tw-text-opacity, 1))}.text-primary{--tw-text-opacity: 1;color:hsl(240 10% 3.9% / var(--tw-text-opacity, 1))}.text-run{--tw-text-opacity: 1;color:hsl(38 92% 50% / var(--tw-text-opacity, 1))}.text-white{--tw-text-opacity: 1;color:rgb(255 255 255 / var(--tw-text-opacity, 1))}.antialiased{-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.opacity-70{opacity:.7}.shadow-lg{--tw-shadow: 0 10px 15px -3px rgb(0 0 0 / .1), 0 4px 6px -4px rgb(0 0 0 / .1);--tw-shadow-colored: 0 10px 15px -3px var(--tw-shadow-color), 0 4px 6px -4px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.shadow-sm{--tw-shadow: 0 1px 2px 0 rgb(0 0 0 / .05);--tw-shadow-colored: 0 1px 2px 0 var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.outline{outline-style:solid}.ring-2{--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow, 0 0 #0000)}.ring-fg\/20{--tw-ring-color: hsl(240 10% 3.9% / .2)}.transition{transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-colors{transition-property:color,background-color,border-color,text-decoration-color,fill,stroke;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-opacity{transition-property:opacity;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}:root{--bg: hsl(0 0% 100%);--fg: hsl(240 10% 3.9%);--muted: hsl(240 4.8% 95.9%);--mutedfg: hsl(240 3.8% 46.1%);--border: hsl(240 5.9% 90%);--card: hsl(0 0% 100%);--agent: hsl(243 75% 59%);--agentbg: hsl(243 100% 98%);--ok: hsl(142 71% 45%);--run: hsl(38 92% 50%);--fail: hsl(0 72% 51%)}body{font-feature-settings:"cv02","cv03","cv04","cv11"}.canvas-grid{background-image:radial-gradient(hsl(240 5.9% 88%) 1px,transparent 1px);background-size:22px 22px}.agent-ring{box-shadow:0 0 0 1px #5048e559,0 0 0 6px #5048e512}.hover\:bg-border:hover{--tw-bg-opacity: 1;background-color:hsl(240 5.9% 90% / var(--tw-bg-opacity, 1))}.hover\:bg-fg\/90:hover{background-color:#09090be6}.hover\:bg-muted:hover{--tw-bg-opacity: 1;background-color:hsl(240 4.8% 95.9% / var(--tw-bg-opacity, 1))}.hover\:text-fg:hover{--tw-text-opacity: 1;color:hsl(240 10% 3.9% / var(--tw-text-opacity, 1))}.hover\:opacity-100:hover{opacity:1}.hover\:opacity-90:hover{opacity:.9}.focus\:outline-none:focus{outline:2px solid transparent;outline-offset:2px}.focus\:ring-1:focus{--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow, 0 0 #0000)}.focus\:ring-primary:focus{--tw-ring-opacity: 1;--tw-ring-color: hsl(240 10% 3.9% / var(--tw-ring-opacity, 1))}.focus-visible\:outline-none:focus-visible{outline:2px solid transparent;outline-offset:2px}.disabled\:pointer-events-none:disabled{pointer-events:none}.disabled\:opacity-50:disabled{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>agentic-surfaces — workflow editor</title>
7
+ <script type="module" crossorigin src="/assets/index-BATbs24P.js"></script>
8
+ <link rel="stylesheet" crossorigin href="/assets/index-CR4Gb62p.css">
9
+ </head>
10
+ <body>
11
+ <div id="root"></div>
12
+ </body>
13
+ </html>
package/dist/http.d.ts ADDED
@@ -0,0 +1,20 @@
1
+ import http from "node:http";
2
+ import type { Workflow } from "@agentic-surfaces/core";
3
+ import type { StreamingObserver } from "./streaming-observer.js";
4
+ /** Minimal run record kept in-memory for the /api/runs endpoint. */
5
+ export interface RunRecord {
6
+ id: string;
7
+ workflow: string;
8
+ status: "running" | "success" | "failed";
9
+ startedAt: number;
10
+ finishedAt?: number;
11
+ }
12
+ export interface ServerOptions {
13
+ port?: number;
14
+ host?: string;
15
+ staticDir?: string;
16
+ workflows?: Workflow[];
17
+ observer: StreamingObserver;
18
+ }
19
+ /** Build an http.Server that serves the workflow-engine API and optional static files. */
20
+ export declare function createServer(opts: ServerOptions): http.Server;
package/dist/http.js ADDED
@@ -0,0 +1,134 @@
1
+ import http from "node:http";
2
+ import { readFile } from "node:fs/promises";
3
+ import { existsSync } from "node:fs";
4
+ import { join } from "node:path";
5
+ function json(res, data, status = 200) {
6
+ const body = JSON.stringify(data);
7
+ res.writeHead(status, {
8
+ "Content-Type": "application/json",
9
+ "Access-Control-Allow-Origin": "*",
10
+ });
11
+ res.end(body);
12
+ }
13
+ function notFound(res) {
14
+ json(res, { error: "not found" }, 404);
15
+ }
16
+ function sseHeaders(res) {
17
+ res.writeHead(200, {
18
+ "Content-Type": "text/event-stream",
19
+ "Cache-Control": "no-cache",
20
+ Connection: "keep-alive",
21
+ "Access-Control-Allow-Origin": "*",
22
+ });
23
+ }
24
+ function writeEvent(res, event) {
25
+ res.write(`data: ${JSON.stringify(event)}\n\n`);
26
+ }
27
+ /** Build an http.Server that serves the workflow-engine API and optional static files. */
28
+ export function createServer(opts) {
29
+ const { observer, workflows = [], staticDir } = opts;
30
+ // In-memory run registry — populated by listening to the observer.
31
+ const runs = new Map();
32
+ let runCounter = 0;
33
+ // Track active run per workflow name (simple: last one wins).
34
+ const activeRuns = new Map();
35
+ observer.subscribe((event) => {
36
+ if (event.type === "run:start") {
37
+ const id = `run_${(++runCounter).toString(16).padStart(4, "0")}`;
38
+ activeRuns.set(event.workflow, id);
39
+ runs.set(id, {
40
+ id,
41
+ workflow: event.workflow,
42
+ status: "running",
43
+ startedAt: event.ts,
44
+ });
45
+ }
46
+ else if (event.type === "run:finish") {
47
+ const id = activeRuns.get(event.workflow);
48
+ if (id) {
49
+ const rec = runs.get(id);
50
+ if (rec) {
51
+ rec.status = event.status ?? "success";
52
+ rec.finishedAt = event.ts;
53
+ }
54
+ }
55
+ }
56
+ });
57
+ async function serveStatic(res, urlPath) {
58
+ if (!staticDir)
59
+ return false;
60
+ const safePath = urlPath === "/" ? "index.html" : urlPath.replace(/^\//, "");
61
+ const filePath = join(staticDir, safePath);
62
+ if (!existsSync(filePath))
63
+ return false;
64
+ try {
65
+ const buf = await readFile(filePath);
66
+ const ext = filePath.split(".").pop() ?? "";
67
+ const mime = {
68
+ html: "text/html; charset=utf-8",
69
+ js: "application/javascript",
70
+ css: "text/css",
71
+ svg: "image/svg+xml",
72
+ ico: "image/x-icon",
73
+ json: "application/json",
74
+ woff2: "font/woff2",
75
+ };
76
+ res.writeHead(200, { "Content-Type": mime[ext] ?? "application/octet-stream" });
77
+ res.end(buf);
78
+ return true;
79
+ }
80
+ catch {
81
+ return false;
82
+ }
83
+ }
84
+ const server = http.createServer(async (req, res) => {
85
+ const url = new URL(req.url ?? "/", `http://localhost`);
86
+ const pathname = url.pathname;
87
+ // CORS preflight
88
+ if (req.method === "OPTIONS") {
89
+ res.writeHead(204, { "Access-Control-Allow-Origin": "*", "Access-Control-Allow-Headers": "*" });
90
+ res.end();
91
+ return;
92
+ }
93
+ // ── API routes ──────────────────────────────────────────────────────────
94
+ if (pathname === "/api/workflows") {
95
+ json(res, workflows.map((w) => ({
96
+ name: w.name,
97
+ nodeCount: w.nodes.length,
98
+ triggerType: w.nodes.find((n) => n.type.startsWith("trigger."))?.type ?? null,
99
+ })));
100
+ return;
101
+ }
102
+ if (pathname === "/api/runs") {
103
+ json(res, [...runs.values()].sort((a, b) => b.startedAt - a.startedAt));
104
+ return;
105
+ }
106
+ if (pathname === "/api/events") {
107
+ // Server-Sent Events — push all buffered events first, then live ones.
108
+ sseHeaders(res);
109
+ // Replay buffered history.
110
+ for (const event of observer.getEvents()) {
111
+ writeEvent(res, event);
112
+ }
113
+ // Subscribe for future events.
114
+ const unsub = observer.subscribe((event) => {
115
+ try {
116
+ writeEvent(res, event);
117
+ }
118
+ catch {
119
+ // client disconnected — unsubscribe below
120
+ }
121
+ });
122
+ // Clean up on client disconnect.
123
+ req.on("close", () => {
124
+ unsub();
125
+ });
126
+ return;
127
+ }
128
+ // ── Static file fallback ─────────────────────────────────────────────────
129
+ if (await serveStatic(res, pathname))
130
+ return;
131
+ notFound(res);
132
+ });
133
+ return server;
134
+ }
@@ -0,0 +1,3 @@
1
+ export * from "./streaming-observer.js";
2
+ export * from "./http.js";
3
+ export * from "./serve.js";
package/dist/index.js ADDED
@@ -0,0 +1,3 @@
1
+ export * from "./streaming-observer.js";
2
+ export * from "./http.js";
3
+ export * from "./serve.js";
@@ -0,0 +1,26 @@
1
+ #!/usr/bin/env node
2
+ import { StreamingObserver } from "./streaming-observer.js";
3
+ export interface ServeOptions {
4
+ port?: number;
5
+ host?: string;
6
+ staticDir?: string;
7
+ }
8
+ /**
9
+ * Locate the built editor assets to serve. Checks, in order:
10
+ * 1. dist/editor — bundled into this package at publish time
11
+ * 2. ../../editor/dist — the sibling @agentic-surfaces/editor build (monorepo / run-from-repo)
12
+ * Returns undefined if neither exists (server still runs; UI just 404s).
13
+ */
14
+ export declare function resolveEditorDir(): string | undefined;
15
+ /**
16
+ * Start the workflow-engine HTTP server.
17
+ *
18
+ * Call this from your own script or use the `flow-server` bin.
19
+ *
20
+ * @returns A teardown function that closes the server.
21
+ */
22
+ export declare function serve(opts?: ServeOptions): {
23
+ observer: StreamingObserver;
24
+ close: () => Promise<void>;
25
+ port: number;
26
+ };
package/dist/serve.js ADDED
@@ -0,0 +1,52 @@
1
+ #!/usr/bin/env node
2
+ import { existsSync } from "node:fs";
3
+ import { dirname, join } from "node:path";
4
+ import { fileURLToPath } from "node:url";
5
+ import { createServer } from "./http.js";
6
+ import { StreamingObserver } from "./streaming-observer.js";
7
+ /**
8
+ * Locate the built editor assets to serve. Checks, in order:
9
+ * 1. dist/editor — bundled into this package at publish time
10
+ * 2. ../../editor/dist — the sibling @agentic-surfaces/editor build (monorepo / run-from-repo)
11
+ * Returns undefined if neither exists (server still runs; UI just 404s).
12
+ */
13
+ export function resolveEditorDir() {
14
+ const here = dirname(fileURLToPath(import.meta.url)); // packages/server/dist
15
+ const candidates = [
16
+ join(here, "editor"),
17
+ join(here, "..", "..", "editor", "dist"),
18
+ ];
19
+ return candidates.find((c) => existsSync(join(c, "index.html")));
20
+ }
21
+ /**
22
+ * Start the workflow-engine HTTP server.
23
+ *
24
+ * Call this from your own script or use the `flow-server` bin.
25
+ *
26
+ * @returns A teardown function that closes the server.
27
+ */
28
+ export function serve(opts = {}) {
29
+ const observer = new StreamingObserver();
30
+ const port = opts.port ?? 4000;
31
+ const host = opts.host ?? "127.0.0.1";
32
+ const staticDir = opts.staticDir ?? resolveEditorDir();
33
+ const server = createServer({ observer, port, host, staticDir });
34
+ server.listen(port, host, () => {
35
+ console.log(`[flow-server] listening on http://${host}:${port}`);
36
+ if (!staticDir) {
37
+ console.log("[flow-server] editor assets not found — API only (build packages/editor for the UI)");
38
+ }
39
+ });
40
+ const close = () => new Promise((resolve, reject) => server.close((err) => (err ? reject(err) : resolve())));
41
+ return { observer, close, port };
42
+ }
43
+ // ── bin entry-point ──────────────────────────────────────────────────────────
44
+ // Only run when executed directly as a script (not when imported as a module).
45
+ const isMain = typeof process !== "undefined" &&
46
+ process.argv[1] != null &&
47
+ (process.argv[1].endsWith("serve.js") || process.argv[1].endsWith("flow-server"));
48
+ if (isMain) {
49
+ const port = parseInt(process.env["PORT"] ?? "4000", 10);
50
+ const staticDir = process.env["STATIC_DIR"];
51
+ serve({ port, staticDir });
52
+ }
@@ -0,0 +1,29 @@
1
+ import type { RunObserver } from "@agentic-surfaces/core";
2
+ /** A single SSE-ready event that the HTTP layer will broadcast. */
3
+ export interface RunEvent {
4
+ type: "run:start" | "node:start" | "node:finish" | "run:finish";
5
+ workflow: string;
6
+ nodeId?: string;
7
+ status?: "success" | "failed";
8
+ meta?: unknown;
9
+ ts: number;
10
+ }
11
+ /**
12
+ * StreamingObserver implements RunObserver and buffers events so the HTTP
13
+ * layer can retrieve them by run or stream them to connected SSE clients.
14
+ */
15
+ export declare class StreamingObserver implements RunObserver {
16
+ private events;
17
+ private listeners;
18
+ private emit;
19
+ /** Subscribe to all future events. Returns an unsubscribe function. */
20
+ subscribe(listener: (event: RunEvent) => void): () => void;
21
+ /** Return a snapshot of all buffered events (safe to call at any time). */
22
+ getEvents(): readonly RunEvent[];
23
+ /** Clear the event buffer (useful between test runs). */
24
+ clear(): void;
25
+ onRunStart(workflow: string): void;
26
+ onNodeStart(nodeId: string): void;
27
+ onNodeFinish(nodeId: string, status: "success" | "failed", meta?: unknown): void;
28
+ onRunFinish(workflow: string, status: "success" | "failed"): void;
29
+ }
@@ -0,0 +1,49 @@
1
+ /**
2
+ * StreamingObserver implements RunObserver and buffers events so the HTTP
3
+ * layer can retrieve them by run or stream them to connected SSE clients.
4
+ */
5
+ export class StreamingObserver {
6
+ events = [];
7
+ listeners = [];
8
+ emit(event) {
9
+ this.events.push(event);
10
+ for (const listener of this.listeners) {
11
+ try {
12
+ listener(event);
13
+ }
14
+ catch {
15
+ // never let a bad listener crash the observer
16
+ }
17
+ }
18
+ }
19
+ /** Subscribe to all future events. Returns an unsubscribe function. */
20
+ subscribe(listener) {
21
+ this.listeners.push(listener);
22
+ return () => {
23
+ this.listeners = this.listeners.filter((l) => l !== listener);
24
+ };
25
+ }
26
+ /** Return a snapshot of all buffered events (safe to call at any time). */
27
+ getEvents() {
28
+ return this.events;
29
+ }
30
+ /** Clear the event buffer (useful between test runs). */
31
+ clear() {
32
+ this.events = [];
33
+ }
34
+ // ── RunObserver interface ──────────────────────────────────────────────────
35
+ onRunStart(workflow) {
36
+ this.emit({ type: "run:start", workflow, ts: Date.now() });
37
+ }
38
+ onNodeStart(nodeId) {
39
+ // workflow name is unknown at this call-site in the core interface;
40
+ // emit a placeholder so the shape stays consistent.
41
+ this.emit({ type: "node:start", workflow: "", nodeId, ts: Date.now() });
42
+ }
43
+ onNodeFinish(nodeId, status, meta) {
44
+ this.emit({ type: "node:finish", workflow: "", nodeId, status, meta, ts: Date.now() });
45
+ }
46
+ onRunFinish(workflow, status) {
47
+ this.emit({ type: "run:finish", workflow, status, ts: Date.now() });
48
+ }
49
+ }
package/package.json ADDED
@@ -0,0 +1,30 @@
1
+ {
2
+ "name": "@agentic-surfaces/server",
3
+ "version": "0.1.4",
4
+ "type": "module",
5
+ "license": "MIT",
6
+ "publishConfig": {
7
+ "access": "public"
8
+ },
9
+ "main": "dist/index.js",
10
+ "types": "dist/index.d.ts",
11
+ "exports": {
12
+ ".": {
13
+ "types": "./dist/index.d.ts",
14
+ "default": "./dist/index.js"
15
+ }
16
+ },
17
+ "bin": {
18
+ "flow-server": "dist/serve.js"
19
+ },
20
+ "files": [
21
+ "dist"
22
+ ],
23
+ "dependencies": {
24
+ "@agentic-surfaces/core": "0.1.4"
25
+ },
26
+ "scripts": {
27
+ "build": "tsc -b",
28
+ "test": "vitest run --root ../.."
29
+ }
30
+ }