trellis

package module
v0.3.2 Latest Latest
Warning

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

Go to latest
Published: Dec 26, 2025 License: AGPL-3.0 Imports: 12 Imported by: 2

README

Trellis

"Faça uma coisa e faça bem feita. Trabalhe com fluxos de texto." - Filosofia Unix

Trellis é um Motor de Máquina de Estados Determinístico (Deterministic State Machine Engine) para a construção de CLIs, fluxos de automação e Guardrails para Agentes de IA.

Ele atua como a espinha dorsal lógica do seu sistema: enquanto sua interface (ou LLM) gerencia a conversa, o Trellis impõe estritamente as regras de negócio e as transições permitidas.

Quick Start

Instalação
git clone https://github.com/aretw0/trellis
cd trellis
go mod tidy
Rodando o Golden Path (Demo)
# Execução do Engine (Demo)
go run ./cmd/trellis ./examples/tour

Usage

Running a Flow
# Interactive mode
trellis run ./my-flow

# Headless mode (for automation/pipes)
echo "start\nyes" | trellis run --headless ./my-flow
Introspection

Visualize your flow as a Mermaid graph:

trellis graph ./my-flow
# Outputs: graph TD ...
Development Mode (Hot Reload)

Iterate faster on your flows by watching for file changes:

trellis run --watch --dir ./my-flow

The engine will monitor your .md, .json, .yaml, and .yml files. When you save a change, the session will automatically reload (preserving the workflow loop).

Documentação

Estrutura

trellis/
├── cmd/           # Entrypoints (trellis CLI)
├── docs/          # Documentação do Projeto
├── examples/      # Demos e Receitas (Tours, Patterns)
├── internal/      # Implementação Privada (Loam Adapter, Runtime)
├── pkg/           # Contratos Públicos (Facade, Domain, Ports)
└── tests/         # Testes de Integração (Certification Suite)

Library vs Framework

O Trellis foi desenhado para ser usado de duas formas:

  1. Como Framework (CLI): Use o executável trellis para rodar pastas de Markdown (loam). Ótimo para scripts rapidos e prototipagem.
  2. Como Biblioteca (Go): Importe github.com/aretw0/trellis e instancie o Engine dentro do seu binário. Você pode injetar grafos em memória, usar banco de dados ou qualquer outra fonte, sem depender de arquivos ou do Loam.

"Opinionated by default (Loam), flexible under the hood (Memory/Custom)."

Documentation

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type ContentRenderer added in v0.3.2

type ContentRenderer func(string) (string, error)

ContentRenderer is a function that transforms the content before outputting it. This allows for TUI rendering (markdown to ANSI) without coupling the core package.

type Engine

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

Engine is the high-level entry point for the Trellis library. It wraps the internal runtime and provides a simplified API for consumers.

func New

func New(repoPath string, opts ...Option) (*Engine, error)

New initializes a new Trellis Engine. By default, it uses a Loam repository at the given path. If WithLoader option is provided, repoPath can be empty and Loam is skipped.

Example (Memory)

ExampleNew_memory demonstrates how to use the Engine with an in-memory graph definition. This is useful for testing, embedded scenarios, or when you don't want to rely on the file system.

package main

import (
	"context"
	"fmt"
	"log"

	"github.com/aretw0/trellis"
	"github.com/aretw0/trellis/pkg/adapters/memory"
	"github.com/aretw0/trellis/pkg/domain"
)

func main() {
	// 1. Define your graph using helper NewFromNodes for clean, type-safe construction.
	loader, err := memory.NewFromNodes(
		domain.Node{
			ID:      "start",
			Type:    "question",
			Content: []byte("Hello! Do you want to proceed? [yes] [no]"),
			Transitions: []domain.Transition{
				{ToNodeID: "yes", Condition: "input == 'yes'"},
				{ToNodeID: "no"},
			},
		},
		domain.Node{
			ID:      "yes",
			Type:    "text",
			Content: []byte("Great! You moved forward."),
		},
		domain.Node{
			ID:      "no",
			Type:    "text",
			Content: []byte("Okay, bye."),
		},
	)
	if err != nil {
		log.Fatal(err)
	}

	// 2. Initialize Trellis with the custom loader
	// Note: We leave path empty ("") because we are providing a loader.
	engine, err := trellis.New("", trellis.WithLoader(loader))
	if err != nil {
		log.Fatal(err)
	}

	// 4. Start the flow
	state := engine.Start()
	ctx := context.Background()

	// 5. Navigate (Input: "yes")
	// "start" -> (input: yes) -> "yes"
	// Note: Example previously captured actions from Step.
	// Render to show we can get actions, then Navigate.
	actions, _, err := engine.Render(ctx, state)
	if err != nil {
		log.Fatal(err)
	}
	// Verify actions from start node (optional in example, but good for completeness)

	nextState, err := engine.Navigate(ctx, state, "yes")
	if err != nil {
		log.Fatal(err)
	}

	fmt.Printf("Current Node: %s\n", nextState.CurrentNodeID)
	for _, action := range actions {
		fmt.Printf("Action: %s\n", action.Type)
	}
}
Output:
Current Node: yes
Action: RENDER_CONTENT

func (*Engine) Inspect

func (e *Engine) Inspect() ([]domain.Node, error)

Inspect returns the full graph definition for visualization or introspection tools.

func (*Engine) Navigate added in v0.3.2

func (e *Engine) Navigate(ctx context.Context, state *domain.State, input string) (*domain.State, error)

Navigate calculates the next state based on the current state and input.

func (*Engine) Render added in v0.3.2

func (e *Engine) Render(ctx context.Context, state *domain.State) ([]domain.ActionRequest, bool, error)

Render generates the actions (view) for the current state without transitioning. Returns actions, isTerminal (true if no transitions), and error.

func (*Engine) Start

func (e *Engine) Start() *domain.State

Start creates the initial state for the flow. It acts as a factory for the first generic State.

func (*Engine) Watch added in v0.3.2

func (e *Engine) Watch(ctx context.Context) (<-chan struct{}, error)

Watch returns a channel that signals when the underlying graph changes. Returns error if the loader does not support watching.

type Option

type Option func(*Engine)

Option defines a functional option for configuring the Engine.

func WithConditionEvaluator

func WithConditionEvaluator(eval runtime.ConditionEvaluator) Option

WithConditionEvaluator sets a custom logic evaluator for the engine.

func WithLoader added in v0.3.1

func WithLoader(l ports.GraphLoader) Option

WithLoader injects a custom GraphLoader, bypassing the default Loam initialization.

type Runner

type Runner struct {
	Input    io.Reader
	Output   io.Writer
	Headless bool
	Renderer ContentRenderer
}

Runner handles the execution loop of the Trellis engine using provided IO. This allows for easy testing and integration with different frontends (CLI, TUI, etc).

func NewRunner

func NewRunner() *Runner

NewRunner creates a new Runner with default Stdin/Stdout. Use SetInput/SetOutput to override for testing.

func (*Runner) Run

func (r *Runner) Run(engine *Engine) error

Run executes the engine loop until termination.

Directories

Path Synopsis
cmd
trellis command
examples
hello-world command
low-level-api command
internal
cli
dto
pkg

Jump to

Keyboard shortcuts

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