flow

package
v0.4.8 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 22, 2026 License: MIT Imports: 31 Imported by: 0

Documentation

Overview

Package flow is tiny's local implementation of the platform FlowService — the gRPC/gRPC-web API the browser editor talks to. It's backed by the cluster's TinyFlow/TinyNode CRDs (via the SDK's resource.Manager) and the shared SDK graph helpers (module/pkg/utils, module/pkg/schema), the same code the hosted platform calls. Only the RPCs the local editor needs are implemented; everything else falls through to UnimplementedFlowServiceServer (platform-only features — LLM prompt, revision history, registry browse).

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func Serve

func Serve(ctx context.Context, addr string, svc *Service, activeProject string, bus *ActivityBus, staticFS http.Handler) error

Serve runs the FlowService as a gRPC-web endpoint on addr (e.g. "127.0.0.1:7775") until ctx is cancelled. The editor's Connect-ES createGrpcWebTransport client talks to it directly — same wire protocol the hosted platform serves — with CORS opened for the localhost browser.

activeProject is the session's fixed project (one per session), surfaced at /api/session so the SPA knows which project to open without a switcher.

staticFS, when non-nil, serves the editor SPA for any non-gRPC request; nil leaves the endpoint gRPC-web-only.

Types

type ActivityBus

type ActivityBus struct {
	// contains filtered or unexported fields
}

ActivityBus is a tiny in-process pub/sub for agent activity. tiny's MCP server publishes an event on every tool call; the editor's WorkspaceActivityService streams them to the dashboard's Activity feed. It keeps a small backlog so a feed that connects mid-session sees recent events.

func NewActivityBus

func NewActivityBus() *ActivityBus

func (*ActivityBus) Publish

func (b *ActivityBus) Publish(kind string)

Publish records an event (kind = e.g. "tool.call.started") and fans it out to live subscribers. Never blocks: a slow subscriber just drops the event.

type Service

type Service struct {
	platform.UnimplementedFlowServiceServer
	// contains filtered or unexported fields
}

Service implements platform.FlowServiceServer against a local cluster.

func NewService

func NewService(cfg *rest.Config, namespace string) *Service

NewService binds the service to one cluster + namespace.

func (*Service) AcquireFlowLock

AcquireFlowLock always grants the lock: a single-user local editor has no contention, and the frontend gates editable rendering on this response.

func (*Service) CreateFlow

func (s *Service) CreateFlow(ctx context.Context, req *platform.CreateFlowRequest) (*platform.Nil, error)

CreateFlow adds a new flow (layer) to the project.

func (*Service) GetComponents

GetComponents lists the installed modules' components for the editor's add-component palette. Each item carries a minimal node graph (module + component); the operator fills in ports on reconcile after the node is created, and the stream updates the editor.

func (*Service) GetFlow

GetFlow returns flow metadata from the TinyFlow CR. The graph itself is streamed by GetFlowStream — the editor reads only ID/ResourceName/Meta here.

func (*Service) GetFlowList

GetFlowList lists the project's flows (the layers) for the flow switcher.

func (*Service) GetFlowStream

GetFlowStream is the render path: it streams the flow's nodes and edges to the canvas, then keeps the graph live as the cluster changes.

This is a stripped buildGraphEvents — the hosted platform overlays otel stats, redis logs, revision notices, and lock state onto the same stream; all of those degrade gracefully, so locally we ship just the graph: WatchNodes → SDK graph maps → node/edge upserts (ADDED/MODIFIED), delete events for elements that disappear, and a 2s heartbeat. The heavy work — schema overlay and edge validation — is the SDK's, identical to the platform.

func (*Service) InspectNode

InspectNode returns a port's data shape — the example/simulated data the editor shows in a node's Debug/Config tab and uses to preview edge mappings. It's backed by the same PortInspector the MCP tools use: it reads the node's reconciled port schema + configuration and returns the example data as JSON, which the editor reads from response.Data.

This is the narrower local inspector (the node's own ports enriched with its own _settings overlay), not the platform's whole-graph simulation — enough for the editor to populate the inspector and edge preview.

func (*Service) ListScenarios

ListScenarios returns the flow's scenarios for the editor's scenario switcher. Local flows have none beyond the implicit Default, so this returns empty — enough to stop the switcher's on-mount call from erroring.

func (*Service) PreviewEdgeMapping

PreviewEdgeMapping applies an edge's configuration mapping to sample source data and returns the mapped result — the live preview in the edge-config panel as you type a mapping. Also pure SDK evaluation.

func (*Service) ReleaseFlowLock

func (s *Service) ReleaseFlowLock(ctx context.Context, req *platform.ReleaseFlowLockRequest) (*platform.Nil, error)

ReleaseFlowLock is a no-op locally.

func (*Service) RunAction

func (s *Service) RunAction(ctx context.Context, req *platform.RunActionRequest) (*platform.Nil, error)

RunAction fires data into a node's port — the editor's "run"/test action on a control widget. Delegates to the injected NATS-backed signal sender.

func (*Service) RunExpression

RunExpression evaluates an ajson expression against sample data and validates the result against a schema — the expression testing + edge-mapping checks in the editor's config panel. Pure SDK evaluation, no cluster access, so it's a direct passthrough to the shared evaluator the platform uses.

func (*Service) SaveFlow

SaveFlow reconciles the editor's whole-graph save into cluster CRs. The editor sends every element of the flow; SaveFlow diffs that against the TinyNodes this flow owns and creates / updates / deletes to match.

It is deliberately conservative: it only ever touches nodes labelled for THIS flow. Nodes owned by other flows (shared into this one) are left untouched even if they appear in the graph, and are never deleted.

func (*Service) SaveFlowMeta

func (s *Service) SaveFlowMeta(ctx context.Context, req *platform.SaveFlowMetaRequest) (*platform.Nil, error)

SaveFlowMeta persists the editor viewport (x/y/zoom) as an annotation on the TinyFlow so it restores on reload.

func (*Service) SetSignalSender

func (s *Service) SetSignalSender(sig sdktools.SignalSender)

SetSignalSender wires the node-fire capability (RunAction). The host passes the same NATS-backed sender the MCP tools use.

func (*Service) SetTraceReader

func (s *Service) SetTraceReader(t traceSource)

SetTraceReader wires the Statistics (traces) capability. The host passes the same otel-collector trace reader the MCP get_traces tools use.

func (*Service) UndeployFlow

func (s *Service) UndeployFlow(ctx context.Context, req *platform.UndeployFlowRequest) (*platform.Nil, error)

UndeployFlow deletes a flow (layer) and all the TinyNodes that belong to it — the editor's flow delete/undeploy action. Locally undeploy IS delete: there's no separate deployed/undeployed state, so it removes the flow outright.

type Tunnel

type Tunnel struct {
	// contains filtered or unexported fields
}

Tunnel keeps the user's localhost in sync with the servers running inside the cluster. A server component (e.g. http_server) binds a random port INSIDE its module's controller-manager pod and reports it as a `listenAddr` of http://localhost:<port> on the node's _control port. That address is the pod's loopback — nothing on the user's machine can reach it. Tunnel watches for those listen addresses and port-forwards each pod:<port> to 127.0.0.1:<port> (the same port), so the URL the editor already shows just works in the browser. Forwards start when a server comes up and stop when it goes away or its pod is replaced.

func NewTunnel

func NewTunnel(cfg *rest.Config, namespace string) (*Tunnel, error)

NewTunnel builds a Tunnel over the same cluster/namespace the editor serves. It creates its own kube client (scheme-aware, lists both TinyNodes and Pods).

func (*Tunnel) Run

func (t *Tunnel) Run(ctx context.Context)

Run reconciles forwards every few seconds until ctx is cancelled, then tears every forward down. Blocking — call it in its own goroutine.

func (*Tunnel) SetLogger

func (t *Tunnel) SetLogger(fn func(string))

SetLogger routes the tunnel's status lines through the host's printer so they match the CLI's style instead of the stdlib log format.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL