mcp

package
v0.14.21 Latest Latest
Warning

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

Go to latest
Published: Jun 3, 2026 License: MIT Imports: 30 Imported by: 0

Documentation

Overview

Package mcp — Data Tables MCP surface. Mirrors the n8n Data Table node + tab: schema CRUD + row CRUD + condition-based filtering.

Package mcp — workflow_describe implementation.

One call returns a human-readable summary of a workflow: triggers, graph shape (entry/leaves/node count), declared dependencies (channels, connector modules, providers), plus a `issues` list of dangling edge targets and templates pointing at undeclared nodes.

Designed as the "give me the lay of the land" call AI authors make before editing — replaces hand-walking workflow_get YAML.

Package mcp — diagnose: error-class classifier + suggested-fix builder. Surface point is the `diagnose=true` flag on workflow_get_run_log; this file is pure (RunState + Workflow + a few registries → Diagnosis) so a future workflow_watch diagnose-on-walk can re-use it without round-tripping back through the connector.

Design rules:

  • Classifier is a registry of regex rules, not a switch. Adding a new error class = drop a new entry. Each rule is a self-contained (pattern, handler) pair.

  • Handlers run with a DiagnoseCtx that carries the run, the workflow, and the registries they need to suggest a fix (Integration for channel events/actions, Connectors for connector ops, Providers for skills). When a registry is nil the handler should degrade gracefully — diagnosis still surfaces the raw error and "I don't know" instead of crashing.

  • Per the no-auto-fix discipline: the result carries a SuggestedFix description, never applies it. AI / user runs workflow_update_node / workflow_set_triggers to act on it.

Package mcp bundles every MCP operation the workflow surface exposes. Wire each method into the existing internal/mcp dispatch layer — transport-agnostic (stdio or HTTP). See workflow-design §9 for the catalog.

Package mcp — workflow_node_detail implementation.

One MCP op resolves a `node_type` key (built-in node, channel event/action, connector op, trigger type) to a unified detail response. Source-of-truth descriptors stay where they live (engine.NodeDescriptor, integration.EventDescriptor / ActionDescriptor, connector.Operation, engine.TriggerDescriptor) — this file is the projector that lifts each one into the same `NodeDetail` JSON shape so AI clients can fetch detail without knowing the per-source struct.

Key format (mirrored in the wick-workflow MCP guide):

agent                              built-in node
channel:slack.message              channel trigger event
channel:slack.send_message         channel action
connector:slack.chat_postMessage   connector op
trigger:cron                       trigger type

All optional fields from wickdocs.Docs are flattened into the response; empty fields are omitted via json:",omitempty" so the AI never branches on null.

Package mcp — workflow_picker_resolve implementation.

Picker fields (channel_id whitelist, user whitelist, etc.) accept only `[{id, name}, ...]` JSON. AI authoring a match filter has to resolve the actual IDs from text the user typed ("#support", "yoga@example.com"). Without help it tends to guess C123 / U456 shapes — which always fail.

workflow_picker_resolve maps a `source` name (matching the wick:"picker=<source>" tag on the field) to a list of `{id, name}` items. The pickers themselves live in setup-injected functions so this package stays free of channel/connector imports.

Package mcp — workflow_template_test implementation.

One-shot Go template renderer that AI clients call to verify a `{{...}}` snippet against a synthetic context without round-tripping through a full edit + workflow_simulate cycle. Errors are introspected: when a missing-key error fires inside a map lookup, the response lists the keys that ARE present at the offending path so the next attempt is informed instead of guessing again.

Package mcp — workflow_validate hint augmentation.

parse.Validate already covers structural errors well; this layer wraps the result with did-you-mean suggestions for the failure modes AI authors hit repeatedly:

  • lowercase JSON keys ("channel" / "channelname" instead of PascalCase ChannelName) when calling set_triggers
  • misspelt match keys (channe_id instead of channel_id)
  • templates pointing at .Event.Foo when the supported root is .Event.Payload

Hints are advisory — surfaced alongside the original Error.Message so existing callers keep working. The Ops.ValidateRich method is the workflow_validate handler going forward; Ops.Validate stays as the low-level shim.

Package mcp — workflow_watch implementation.

Watch is deliberately bounded:

  • Reads come from the sharded run index. Per-run state.Load only happens when a filter needs node_id / trigger_id, and even then it stops the moment `limit` results are collected.

  • wait_seconds is an UPPER bound. The handler subscribes to Engine's event broker, returns the instant the target count is met, and otherwise waits the remaining time.

  • All inputs are caps (limit ≤ 50, wait_seconds ≤ 30). AI can never trigger a long-running scan by accident.

See doc 25 for the full design notes.

Index

Constants

View Source
const (
	KindBuiltIn       = "built_in"
	KindChannelEvent  = "channel_event"
	KindChannelAction = "channel_action"
	KindConnectorOp   = "connector_op"
	KindTrigger       = "trigger"
)

Detail kinds, exposed via NodeDetail.Kind.

Variables

This section is empty.

Functions

func WorkspaceFormatContracts

func WorkspaceFormatContracts() map[string]any

WorkspaceFormatContracts returns structured format rules AI must follow when writing workflow YAML or trigger JSON. Exposed via workflow_workspace so AI reads them once at session start instead of relying on prose descriptions.

Types

type CanvasStats added in v0.14.20

type CanvasStats struct {
	NodeCount    int `json:"node_count"`
	TriggerCount int `json:"trigger_count"`
	EdgeCount    int `json:"edge_count"`
	Unpositioned int `json:"unpositioned"`
}

CanvasStats summarises the canvas composition.

type CanvasViewResult added in v0.14.20

type CanvasViewResult struct {
	Nodes    []CanvasViewRow `json:"nodes"`
	Triggers []CanvasViewRow `json:"triggers"`
	ASCII    string          `json:"ascii"`
	Stats    CanvasStats     `json:"stats"`
}

CanvasViewResult is the response for workflow_canvas_view.

type CanvasViewRow added in v0.14.20

type CanvasViewRow struct {
	ID      string   `json:"id"`
	Label   string   `json:"label,omitempty"`
	Type    string   `json:"type"`
	X       int      `json:"x"`
	Y       int      `json:"y"`
	EdgesTo []string `json:"edges_to,omitempty"`
}

CanvasViewRow is one entry in the canvas table (node or trigger).

type CreateInput

type CreateInput struct {
	ID       string `json:"id,omitempty"`
	Template string `json:"template,omitempty"`
	Name     string `json:"name,omitempty"`
}

CreateInput is the payload for `workflow_create`.

ID is the on-disk folder name. Optional — when empty, Create generates a UUID so renaming the display name later doesn't break run history, indexed logs, or shared edit URLs. Power users (MCP, CLI, tests) may pin an explicit id for human-readable folders.

type DataTableCreateInput added in v0.13.1

type DataTableCreateInput struct {
	Slug       string             `json:"slug"`
	Mode       string             `json:"mode,omitempty"`
	PrimaryKey []string           `json:"primary_key,omitempty"`
	Columns    []datatable.Column `json:"columns"`
	Access     *datatable.Access  `json:"access,omitempty"`
}

DataTableCreateInput is the payload for datatable_create.

type DataTableDeleteInput added in v0.13.1

type DataTableDeleteInput struct {
	Slug       string                `json:"slug"`
	Where      map[string]any        `json:"where,omitempty"`
	Conditions []datatable.Condition `json:"conditions,omitempty"`
}

DataTableDeleteInput is the payload for datatable_delete.

type DataTableInsertInput added in v0.13.1

type DataTableInsertInput struct {
	Slug string         `json:"slug"`
	Row  map[string]any `json:"row"`
}

DataTableInsertInput is the payload for datatable_insert / upsert.

type DataTableQueryInput added in v0.13.1

type DataTableQueryInput struct {
	Slug       string                    `json:"slug"`
	Where      map[string]any            `json:"where,omitempty"`
	Conditions []datatable.Condition     `json:"conditions,omitempty"`
	OrderBy    []workflow.DataTableOrder `json:"order_by,omitempty"`
	Limit      int                       `json:"limit,omitempty"`
	Offset     int                       `json:"offset,omitempty"`
}

DataTableQueryInput is the payload for datatable_query.

type DataTableSummary added in v0.13.1

type DataTableSummary struct {
	Slug     string `json:"slug"`
	Name     string `json:"name,omitempty"`
	Mode     string `json:"mode,omitempty"`
	Columns  int    `json:"columns"`
	RowCount int    `json:"row_count"`
}

DataTableSummary is the row shape for datatable_list.

type DescribeDeps

type DescribeDeps struct {
	Channels   []string            `json:"channels,omitempty"`
	Connectors []string            `json:"connectors,omitempty"`
	Providers  []string            `json:"providers,omitempty"`
	Other      map[string][]string `json:"other,omitempty"`
}

DescribeDeps lists external surfaces the workflow touches.

Channels / Connectors / Providers stay as flat string lists so existing callers / UIs keep working. Other dependency kinds (sheets, webhooks, custom) surface under Other, keyed by Kind.

type DescribeIssue

type DescribeIssue struct {
	Level   string `json:"level"`
	Message string `json:"message"`
	Path    string `json:"path,omitempty"`
}

DescribeIssue is one anomaly found during the walk. Level is "warning" or "error"; Message + Path tell the caller where to look.

type DescribeResult

type DescribeResult struct {
	ID           string           `json:"id"`
	Name         string           `json:"name"`
	Enabled      bool             `json:"enabled"`
	Summary      string           `json:"summary,omitempty"`
	Triggers     []TriggerSummary `json:"triggers"`
	Graph        GraphSummary     `json:"graph"`
	Dependencies DescribeDeps     `json:"dependencies"`
	Issues       []DescribeIssue  `json:"issues,omitempty"`
}

DescribeResult is the workflow_describe response.

type DiagnoseCtx

type DiagnoseCtx struct {
	Ctx         context.Context
	State       workflow.RunState
	Workflow    workflow.Workflow
	Integration *integration.Registry
	Connectors  *connector.Registry
	Providers   *provider.Registry
	// Match is the regex submatch slice (Match[0] is the full hit;
	// Match[1..] are capture groups). Always populated for rules that
	// supply a pattern.
	Match []string
}

DiagnoseCtx is the surface a classifier rule sees. Kept small and explicit so rules don't reach into mcp.Ops directly.

type Diagnosis

type Diagnosis struct {
	ErrorClass    string        `json:"error_class,omitempty"`
	FailedNode    string        `json:"failed_node,omitempty"`
	Field         string        `json:"field,omitempty"`
	Summary       string        `json:"diagnosis,omitempty"`
	AvailableKeys []string      `json:"available_keys,omitempty"`
	SuggestedFix  *SuggestedFix `json:"suggested_fix,omitempty"`
	PathTaken     []string      `json:"path_taken,omitempty"`
	NextActions   []string      `json:"next_actions,omitempty"`
	Status        string        `json:"status,omitempty"`
}

Diagnosis is the structured response attached to a failed-run reply when the caller passed `diagnose=true`. A successful run still gets a Diagnosis, but with ErrorClass empty and PathTaken populated.

type ErrorHint

type ErrorHint struct {
	Path       string   `json:"path"`
	Message    string   `json:"message"`
	DidYouMean []string `json:"did_you_mean,omitempty"`
	Hint       string   `json:"hint,omitempty"`
}

ErrorHint extends parse.Error with optional remediation pointers.

type ExecNodeInput added in v0.14.20

type ExecNodeInput struct {
	Node        workflow.Node             `json:"node"`
	Input       map[string]any            `json:"input"`
	Event       map[string]any            `json:"event"`
	ParentID    string                    `json:"parent_id"`
	NodeOutputs map[string]map[string]any `json:"node_outputs"`
}

ExecNodeInput is the request shape for ExecNode.

type GraphSummary

type GraphSummary struct {
	Entry     string   `json:"entry,omitempty"`
	NodeCount int      `json:"node_count"`
	EdgeCount int      `json:"edge_count"`
	Leaves    []string `json:"leaves,omitempty"`
	NodeTypes []string `json:"node_types,omitempty"`
}

GraphSummary describes the DAG's shape.

type NodeDetail

type NodeDetail struct {
	NodeType    string         `json:"node_type"`
	Kind        string         `json:"kind"`
	Name        string         `json:"name,omitempty"`
	Description string         `json:"description,omitempty"`
	WhenToUse   string         `json:"when_to_use,omitempty"`
	Destructive bool           `json:"destructive,omitempty"`
	Schema      map[string]any `json:"schema,omitempty"`
	Output      map[string]any `json:"output,omitempty"`
	MatchSchema map[string]any `json:"match_schema,omitempty"`
	Example     string         `json:"example,omitempty"`
	wickdocs.Docs
}

NodeDetail is the unified `workflow_node_detail` response.

Kind is set per-source so the AI can disambiguate which prefix to re-use when chasing PairWith links; it is informational only.

type NodeTypeInfo

type NodeTypeInfo struct {
	Type        string         `json:"type"`
	Description string         `json:"description"`
	Schema      map[string]any `json:"schema"`
	Example     string         `json:"example,omitempty"`
	WhenToUse   string         `json:"when_to_use"`
	// Palette metadata mirrored from engine.NodeDescriptor so the
	// editor's Add Node picker can render category/label/badge
	// straight from this row instead of carrying a parallel map.
	Category string `json:"category,omitempty"`
	Label    string `json:"label,omitempty"`
	Badge    string `json:"badge,omitempty"`
}

NodeTypeInfo is one row of the node-type catalog.

func NodeTypesCatalog

func NodeTypesCatalog(eng *engine.Engine) []NodeTypeInfo

NodeTypesCatalog returns the AI-introspectable node type metadata, built entirely from Engine.Descriptors — single source of truth lives in each node executor's Descriptor() method.

type Ops

type Ops struct {
	Service     service.Service
	Engine      *engine.Engine
	Router      *trigger.Router
	Canvas      *canvas.Canvas
	Channels    *channel.Registry
	Connectors  *connector.Registry
	Providers   *provider.Registry
	DataTables  datatable.Service
	StateStore  state.Store
	Integration *integration.Registry
	// Guard runs safety policy rules (destructive shell, secret leak,
	// SQL injection, network allowlist). Powers workflow_guard. Nil
	// when not wired — handler returns 503-equivalent.
	Guard *guard.Guard
	// Repo is the DB-backed workflow store. Nil when no DB is wired —
	// version history + restore handlers fall back to the file-store
	// equivalents the Service surfaces.
	Repo *repository.Repo
	// Pickers maps picker source names (e.g. "slack.channels") to
	// resolver functions wired at setup. Powers workflow_picker_resolve.
	// Always non-nil after New(); setup code registers sources via
	// Pickers.Register(...). See picker.go.
	Pickers *PickerRegistry
}

Ops bundles every MCP operation surface.

func New

func New(svc service.Service, e *engine.Engine, router *trigger.Router, c *canvas.Canvas, channels *channel.Registry, connectors *connector.Registry, providers *provider.Registry, dataTables datatable.Service, ss state.Store) *Ops

New wires the dispatcher.

func (*Ops) AddNode

func (m *Ops) AddNode(id string, n workflow.Node) (workflow.Workflow, error)

AddNode wraps Canvas.AddNode.

func (*Ops) AutoLayout added in v0.14.20

func (m *Ops) AutoLayout(id string, nodeIDs []string) (workflow.Workflow, error)

AutoLayout wraps Canvas.AutoLayout — DAG-aware position compute + apply.

func (*Ops) CanvasView added in v0.14.20

func (m *Ops) CanvasView(id string) (CanvasViewResult, error)

CanvasView returns a human-readable table + ASCII sketch of the workflow canvas. Pure read — no side effects.

func (*Ops) ChannelsList

func (m *Ops) ChannelsList() []channel.Info

ChannelsList returns the channel registry introspection rows.

func (*Ops) Connect

func (m *Ops) Connect(id, from, to, caseLabel string) (workflow.Workflow, error)

Connect wraps Canvas.Connect.

func (*Ops) ConnectorsList

func (m *Ops) ConnectorsList() []connector.Info

ConnectorsList returns the connector registry introspection rows.

func (*Ops) Create

func (m *Ops) Create(in CreateInput) (workflow.Workflow, error)

Create scaffolds a new workflow from a template.

func (*Ops) DataTableCount added in v0.13.1

func (m *Ops) DataTableCount(in DataTableDeleteInput) (int, error)

DataTableCount counts rows.

func (*Ops) DataTableCreate added in v0.13.1

func (m *Ops) DataTableCreate(in DataTableCreateInput) error

DataTableCreate registers a new table.

func (*Ops) DataTableDelete added in v0.13.1

func (m *Ops) DataTableDelete(in DataTableDeleteInput) (int, error)

DataTableDelete removes rows; Conditions wins over Where when both set.

func (*Ops) DataTableDrop added in v0.13.1

func (m *Ops) DataTableDrop(slug string) error

DataTableDrop removes a table and all its rows.

func (*Ops) DataTableGet added in v0.13.1

func (m *Ops) DataTableGet(slug string) (map[string]any, error)

DataTableGet returns schema + sample rows for one table.

func (*Ops) DataTableInsert added in v0.13.1

func (m *Ops) DataTableInsert(in DataTableInsertInput) error

DataTableInsert inserts a new row.

func (*Ops) DataTableList added in v0.13.1

func (m *Ops) DataTableList() ([]DataTableSummary, error)

DataTableList returns every registered table with row count.

func (*Ops) DataTableQuery added in v0.13.1

func (m *Ops) DataTableQuery(in DataTableQueryInput) ([]map[string]any, error)

DataTableQuery returns rows matching either Where (equality) or Conditions (richer ops). When both are set, Conditions wins.

func (*Ops) DataTableUpdateSchema added in v0.13.1

func (m *Ops) DataTableUpdateSchema(slug string, sc datatable.Schema) error

DataTableUpdateSchema replaces the schema of an existing table.

func (*Ops) DataTableUpsert added in v0.13.1

func (m *Ops) DataTableUpsert(in DataTableInsertInput) (string, error)

DataTableUpsert insert-or-updates by PK.

func (*Ops) Delete

func (m *Ops) Delete(id string) error

Delete removes the workflow folder + unregisters scheduling.

func (*Ops) DeleteNode

func (m *Ops) DeleteNode(id, nodeID string) (workflow.Workflow, error)

DeleteNode wraps Canvas.DeleteNode.

func (*Ops) DeleteTest added in v0.14.20

func (m *Ops) DeleteTest(id, name string) error

DeleteTest drops one test case by name.

func (*Ops) Describe

func (m *Ops) Describe(id string) (DescribeResult, error)

Describe builds the summary for one workflow id.

func (*Ops) Diagnose

func (m *Ops) Diagnose(ctx context.Context, w workflow.Workflow, st workflow.RunState) Diagnosis

Diagnose returns the structured diagnosis for a run. Success paths produce a Diagnosis with Status="success" + PathTaken populated. Failed paths classify the error and (when possible) propose a fix.

The function is safe to call with nil registries — handlers degrade to "I don't know" rather than crash.

func (*Ops) DiffVersions added in v0.14.20

func (m *Ops) DiffVersions(id string, fromID, toID uint) (VersionDiff, error)

DiffVersions resolves both version ids on the same workflow and returns their full bodies for client-side diff rendering.

func (*Ops) Disconnect

func (m *Ops) Disconnect(id, from, to string) (workflow.Workflow, error)

Disconnect wraps Canvas.Disconnect.

func (*Ops) ExecNode added in v0.14.20

func (m *Ops) ExecNode(ctx context.Context, id string, body ExecNodeInput) (map[string]any, error)

ExecNode runs one node in isolation — n8n's "Execute step" pattern. Returns the node output + latency. Nothing persists to runs/. The caller passes a prefill of upstream outputs via NodeOutputs so {{.Node.<upstream>}} template refs resolve.

func (*Ops) Get

func (m *Ops) Get(id string) (workflow.Workflow, error)

Get returns the full workflow.

func (*Ops) GetRunSummaries

func (m *Ops) GetRunSummaries(id string, page, pageSize int) ([]RunSummary, bool, error)

GetRunSummaries returns one page of recent runs, newest first. Reads from the sharded index (`runs/index/<date>-<seq>.jsonl`) instead of scanning the per-run subdirs, so the cost stays constant whether the workflow has 10 or 100,000 historical runs. hasMore=true when older pages exist.

func (*Ops) GetRuns

func (m *Ops) GetRuns(id string, limit int) ([]string, error)

GetRuns returns recent run IDs for an id.

func (*Ops) GetTest added in v0.14.20

func (m *Ops) GetTest(id, name string) ([]byte, error)

GetTest returns one test case body by name.

func (*Ops) GuardReport added in v0.14.20

func (m *Ops) GuardReport(ctx context.Context, id string) (guard.Report, error)

GuardReport runs guard.Review against the draft and returns the report. Distinct from workflow_validate — guard inspects safety policy (destructive shell, secret leak, unparameterized SQL, network allowlist) while validate inspects graph structure (cycles, schema).

func (*Ops) IntegrationActions

func (m *Ops) IntegrationActions() []integration.ActionDescriptor

IntegrationActions returns every registered action descriptor.

func (*Ops) IntegrationEvents

func (m *Ops) IntegrationEvents() []integration.EventDescriptor

IntegrationEvents returns every registered event descriptor across all channels. Includes MatchSchema + PayloadType for full filter discovery.

func (*Ops) List

func (m *Ops) List() ([]Summary, error)

List returns workflow IDs + metadata.

func (*Ops) ListTests added in v0.14.20

func (m *Ops) ListTests(id string) ([]string, error)

ListTests returns every test case name registered under the workflow.

func (*Ops) MoveNode

func (m *Ops) MoveNode(id, nodeID string, x, y int) (workflow.Workflow, error)

MoveNode wraps Canvas.MoveNode.

func (*Ops) MoveNodes added in v0.14.20

func (m *Ops) MoveNodes(id string, moves []canvas.NodeMove) (workflow.Workflow, error)

MoveNodes wraps Canvas.MoveNodes — batch position update.

func (*Ops) NodeDetail

func (m *Ops) NodeDetail(nodeType string) (NodeDetail, error)

NodeDetail returns the unified detail for one node_type key, or an error when the key is malformed or not registered.

Resolution order is by prefix — `channel:`, `connector:`, `trigger:` route to the matching registry; everything else is treated as a built-in node type. Unknown keys return an "unknown node_type" error so AI clients see a clean signal rather than an empty payload.

func (*Ops) NodeTypes

func (m *Ops) NodeTypes() []NodeTypeInfo

NodeTypes returns the catalog used by `workflow_node_types`. Built from Engine.Descriptors — populated by each executor's Descriptor().

func (*Ops) PickerResolve

func (m *Ops) PickerResolve(ctx context.Context, in PickerResolveInput) (PickerResolveResult, error)

PickerResolve looks up the picker source and returns matching items. Filtering is applied client-side after the resolver returns so sources don't have to implement filtering uniformly.

func (*Ops) ProvidersList

func (m *Ops) ProvidersList() []provider.Info

ProvidersList returns the provider registry introspection rows.

func (*Ops) RestoreVersion added in v0.14.20

func (m *Ops) RestoreVersion(id string, versionID uint, createdBy string) (uint, error)

RestoreVersion writes a historic snapshot back to the draft slot. No auto-publish — the user must hit Publish to make the restore live. Returns the new draft snapshot id.

func (*Ops) RunNow

func (m *Ops) RunNow(ctx context.Context, id string, evt workflow.Event) error

RunNow enqueues a manual run for one explicit id. Bypasses Enabled + trigger-match checks so admins can fire a disabled workflow from the UI Run-Now button. Compare with Router.Dispatch which is the trigger-source path.

func (*Ops) RunNowWith

func (m *Ops) RunNowWith(ctx context.Context, id string, w *workflow.Workflow, evt workflow.Event) error

RunNowWith fires a single run with an explicit Workflow override. The UI uses this so Run Now executes the freshly-saved DRAFT (workflow.draft.yaml) without waiting for Publish — router's registered copy stays on the published version so cron / channel / webhook triggers keep firing live.

func (*Ops) SaveTest added in v0.14.20

func (m *Ops) SaveTest(id, name string, body []byte) error

SaveTest upserts one test case body.

func (*Ops) SetLock added in v0.14.20

func (m *Ops) SetLock(id string, locked bool) error

SetLock flips workflow.Canvas["locked"]. Dedicated path so toggling works even while the workflow IS locked (the regular SaveDraft would be blocked by Service.SaveDraft's lock guard); also skips validation — locking shouldn't fail because the draft has a half-built node.

func (*Ops) SetTriggers

func (m *Ops) SetTriggers(id string, triggers []workflow.Trigger) (workflow.Workflow, error)

SetTriggers wraps Canvas.SetTriggers.

func (*Ops) Simulate

func (m *Ops) Simulate(ctx context.Context, id string, evt workflow.Event) (workflow.RunState, error)

Simulate dry-runs a workflow with a synthetic event.

func (*Ops) SkillsList

func (m *Ops) SkillsList(ctx context.Context, providerName string) ([]provider.Skill, error)

SkillsList returns the catalog from one or all providers.

func (*Ops) TemplateTest

func (m *Ops) TemplateTest(in TemplateTestInput) (TemplateTestResult, error)

TemplateTest renders `in.Template` against the resolved context and returns a structured result.

func (*Ops) Toggle

func (m *Ops) Toggle(id string, enabled bool) (workflow.Workflow, error)

Toggle wraps Canvas.Toggle.

func (*Ops) TriggerTypes

func (m *Ops) TriggerTypes() []TriggerTypeInfo

TriggerTypes returns the catalog used by `workflow_trigger_types`.

func (*Ops) UpdateNode

func (m *Ops) UpdateNode(id, nodeID string, patch map[string]any) (workflow.Workflow, error)

UpdateNode wraps Canvas.UpdateNode.

func (*Ops) Validate

func (m *Ops) Validate(id string) ValidateResult

Validate runs parse + validate (no guard).

func (*Ops) ValidateRich

func (m *Ops) ValidateRich(id string) ValidateRichResult

ValidateRich runs parse.Validate and decorates each Error with did-you-mean / hint pointers. Used by workflow_validate.

func (*Ops) VersionDetail added in v0.14.20

func (m *Ops) VersionDetail(versionID uint) (entity.WorkflowVersion, error)

VersionDetail returns one snapshot including its full body JSON. Used by the FE to populate the diff viewer when the user compares two versions side-by-side.

func (*Ops) Versions added in v0.14.20

func (m *Ops) Versions(id string) ([]VersionSummary, error)

Versions returns the history rows for a workflow ordered newest first. Powers the SPA history panel and the workflow_versions MCP op. Empty list when no DB is wired.

func (*Ops) Watch

func (m *Ops) Watch(ctx context.Context, in WatchInput) (WatchResult, error)

Watch resolves runs matching the filter, optionally subscribing to the live engine broker for wait_seconds.

func (*Ops) WithIntegration

func (m *Ops) WithIntegration(reg *integration.Registry) *Ops

WithIntegration wires the integration registry so workflow_integration can expose per-channel event + action descriptors (incl. MatchSchema) independent of the live Channel registry. Useful for stdio MCP where no Slack channel runs but AI still needs full filter schemas.

func (*Ops) Workspace

func (m *Ops) Workspace() map[string]any

Workspace returns the entry-point response for `workflow_workspace`.

type PickerFunc

type PickerFunc func(ctx context.Context, query string) ([]PickerItem, error)

PickerFunc is the per-source resolver signature. query is an optional case-insensitive substring filter the caller passes — the implementation MAY ignore it and return everything if filtering is cheap downstream.

type PickerItem

type PickerItem struct {
	ID   string `json:"id"`
	Name string `json:"name"`
}

PickerItem is one row a picker source returns. id is what the router matches against; name is shown to humans.

type PickerRegistry

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

PickerRegistry holds the wired (source → resolver) map. Concurrent- safe — registration happens at setup; reads happen per MCP call.

Wiring is intentionally external: setup code that owns the slack channel / connector instances calls Register("slack.channels", fn) rather than mcp importing slack. Keeps the mcp package free of channel-specific imports.

func NewPickerRegistry

func NewPickerRegistry() *PickerRegistry

NewPickerRegistry constructs an empty registry. The Ops struct auto-creates one in New().

func (*PickerRegistry) Get

func (r *PickerRegistry) Get(source string) (PickerFunc, bool)

Get returns the resolver for source, or (nil, false).

func (*PickerRegistry) Register

func (r *PickerRegistry) Register(source string, fn PickerFunc)

Register adds (or replaces) one source. Idempotent — setup may call this multiple times during hot-reload.

func (*PickerRegistry) Sources

func (r *PickerRegistry) Sources() []string

Sources lists the registered source names, sorted. Used in error messages so AI sees what IS available when it asks for something that's not.

type PickerResolveInput

type PickerResolveInput struct {
	Source string `json:"source"`
	Query  string `json:"query,omitempty"`
	Limit  int    `json:"limit,omitempty"`
}

PickerResolveInput is the workflow_picker_resolve request.

type PickerResolveResult

type PickerResolveResult struct {
	Items []PickerItem `json:"items"`
	// Truncated reports whether the resolver returned more items than
	// the caller asked for (after Limit was applied).
	Truncated bool `json:"truncated,omitempty"`
}

PickerResolveResult is the response.

type RunSummary

type RunSummary struct {
	ID        string     `json:"id"`
	Status    string     `json:"status"`
	StartedAt time.Time  `json:"started_at"`
	EndedAt   *time.Time `json:"ended_at,omitempty"`
	// Provenance fields — mirrored from the run's index entry so the
	// editor can show source / trigger pills without re-loading each
	// run's state.json. Empty for legacy runs that pre-date the
	// IndexEntry change.
	Source      string `json:"source,omitempty"`
	TriggerID   string `json:"trigger_id,omitempty"`
	TriggerType string `json:"trigger_type,omitempty"`
}

RunSummary is the lightweight row the editor's Runs panel shows — ID + started timestamp + status. Loaded eagerly because the panel only displays the most recent N runs (default 20) and one state.json read per run is cheap.

type SuggestedFix

type SuggestedFix struct {
	NodeID     string `json:"node_id"`
	Field      string `json:"field,omitempty"`
	Current    string `json:"current,omitempty"`
	Suggested  string `json:"suggested,omitempty"`
	Confidence string `json:"confidence"`
	Rationale  string `json:"rationale,omitempty"`
}

SuggestedFix carries a concrete patch the AI can show to the user before running workflow_update_node. confidence is one of "high" | "medium" | "low" — see doc 25 §"Confidence levels".

type Summary

type Summary struct {
	ID        string    `json:"id"`
	Name      string    `json:"name"`
	Enabled   bool      `json:"enabled"`
	Version   int       `json:"version"`
	CreatedAt time.Time `json:"created_at,omitempty"`
	UpdatedAt time.Time `json:"updated_at,omitempty"`
}

Summary is the row shape for `workflow_list`.

type TemplateTestInput

type TemplateTestInput struct {
	Template    string `json:"template"`
	Context     string `json:"context,omitempty"`
	SampleEvent string `json:"sample_event,omitempty"`
}

TemplateTestInput is the payload for workflow_template_test.

Context is a JSON-encoded RenderCtx-shaped object. Top-level keys "Event", "Node", "Env", "Secret", "Workflow", "Run", "Dataset" are projected onto the typed RenderCtx; unknown keys are ignored so the caller can hand in whatever they have without ceremony.

SampleEvent picks a built-in synthetic event payload. When non-empty it OVERWRITES the .Event branch of context — the caller can use SampleEvent alone for the easy cases, or mix it with a hand-built .Node context for richer scenarios.

type TemplateTestResult

type TemplateTestResult struct {
	OK            bool     `json:"ok"`
	Rendered      string   `json:"rendered,omitempty"`
	Error         string   `json:"error,omitempty"`
	At            string   `json:"at,omitempty"`
	AvailableKeys []string `json:"available_keys,omitempty"`
	Hint          string   `json:"hint,omitempty"`
}

TemplateTestResult is the workflow_template_test response.

On success Rendered carries the output and Error is empty. On failure Error explains the failure, and when the failure is a missing-key error wick introspects the context at the offending path and lists the keys that ARE present.

type TriggerSummary

type TriggerSummary struct {
	ID        string `json:"id,omitempty"`
	Type      string `json:"type"`
	EntryNode string `json:"entry_node"`
	Schedule  string `json:"schedule,omitempty"`
	Channel   string `json:"channel,omitempty"`
	Event     string `json:"event,omitempty"`
	Path      string `json:"path,omitempty"`
	MatchOn   string `json:"match_on,omitempty"`
}

TriggerSummary collapses a workflow.Trigger to the fields a human (or AI) needs at a glance.

type TriggerTypeInfo

type TriggerTypeInfo struct {
	Type        string         `json:"type"`
	Description string         `json:"description"`
	Schema      map[string]any `json:"schema"`
	Example     string         `json:"example,omitempty"`
}

TriggerTypeInfo is one row of the trigger-type catalog.

func TriggerTypesCatalog

func TriggerTypesCatalog() []TriggerTypeInfo

TriggerTypesCatalog returns the trigger-type metadata.

type ValidateResult

type ValidateResult struct {
	OK       bool          `json:"ok"`
	Errors   []parse.Error `json:"errors,omitempty"`
	Warnings []parse.Error `json:"warnings,omitempty"`
}

ValidateResult is the response for `workflow_validate`.

type ValidateRichResult

type ValidateRichResult struct {
	OK       bool        `json:"ok"`
	Errors   []ErrorHint `json:"errors,omitempty"`
	Warnings []ErrorHint `json:"warnings,omitempty"`
}

ValidateRichResult is the augmented response for workflow_validate.

Errors and Warnings carry the same Path + Message as parse.Result plus an optional DidYouMean / Hint pair. Hint is a human-readable remediation pointer the caller can show verbatim; DidYouMean lists likely-intended values for "unknown field" / "unknown key" errors.

type VersionDiff added in v0.14.20

type VersionDiff struct {
	From entity.WorkflowVersion `json:"from"`
	To   entity.WorkflowVersion `json:"to"`
}

DiffVersions returns the body of two snapshots so the caller can render a diff. Body is shipped as JSON strings; the FE picks its own diff library to render.

type VersionSummary added in v0.14.20

type VersionSummary struct {
	ID         uint      `json:"id"`
	WorkflowID string    `json:"workflow_id"`
	Kind       string    `json:"kind"`
	Message    string    `json:"message,omitempty"`
	CreatedBy  string    `json:"created_by,omitempty"`
	CreatedAt  time.Time `json:"created_at"`
}

VersionSummary is the narrow projection of one workflow_versions row callers actually need. Body is held back from the list view — fetching every snapshot's full JSON would balloon the response.

type WatchInput

type WatchInput struct {
	WorkflowID  string `json:"workflow_id,omitempty"`
	TriggerID   string `json:"trigger_id,omitempty"`
	NodeID      string `json:"node_id,omitempty"`
	Status      string `json:"status,omitempty"` // any | success | failed | running
	Since       string `json:"since,omitempty"`  // RFC3339 absolute or "-15m" relative
	Limit       int    `json:"limit,omitempty"`
	WaitSeconds int    `json:"wait_seconds,omitempty"`
	Expect      int    `json:"expect,omitempty"`
	StopOnFirst bool   `json:"stop_on_first,omitempty"`
}

WatchInput is the workflow_watch request shape.

type WatchResult

type WatchResult struct {
	Runs         []WatchRow `json:"runs"`
	CheckedUntil time.Time  `json:"checked_until"`
	Truncated    bool       `json:"truncated,omitempty"`
}

WatchResult is the response.

type WatchRow

type WatchRow struct {
	RunID      string     `json:"run_id"`
	WorkflowID string     `json:"workflow_id"`
	Status     string     `json:"status,omitempty"`
	TriggerID  string     `json:"trigger_id,omitempty"`
	StartedAt  time.Time  `json:"started_at"`
	EndedAt    *time.Time `json:"ended_at,omitempty"`
}

WatchRow is one returned run summary. Deliberately tiny — downstream calls workflow_get_run_log per id when it wants more.

Jump to

Keyboard shortcuts

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