loop

package
v0.1.3 Latest Latest
Warning

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

Go to latest
Published: Sep 18, 2026 License: Apache-2.0 Imports: 10 Imported by: 0

Documentation

Overview

Package loop provides fixed and dynamic activation policies for continuation executions.

A Controller plans one durable wait after each completed Work result. The package never sleeps, polls, starts a timer, or resumes an execution; applications explicitly deliver due-time or signal activations through continuation.

Index

Examples

Constants

This section is empty.

Variables

View Source
var (
	ErrInvalid  = errors.New("loop: invalid value")
	ErrTooLarge = errors.New("loop: value too large")
)

Loop validation errors.

Functions

This section is empty.

Types

type Controller

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

Controller maps activation plans onto durable continuation waits.

func Every

func Every(interval time.Duration, options ...ControllerOption) (*Controller, error)

Every constructs a fixed-interval Loop Controller.

Example
package main

import (
	"context"
	"fmt"
	"time"

	"github.com/rsbin1178/pips/agent/continuation"
	"github.com/rsbin1178/pips/agent/loop"
	"github.com/rsbin1178/pips/ai"
)

type exampleClock struct {
	now time.Time
}

func (clock *exampleClock) Now() time.Time { return clock.now }

type exampleWorker func(context.Context, continuation.WorkRequest) (continuation.WorkResult, error)

func (worker exampleWorker) Run(
	ctx context.Context,
	request continuation.WorkRequest,
) (continuation.WorkResult, error) {
	return worker(ctx, request)
}

func main() {
	clock := &exampleClock{now: time.Date(2026, time.July, 19, 8, 0, 0, 0, time.UTC)}
	controller, _ := loop.Every(5*time.Minute,
		loop.WithClock(clock),
	)
	setup, _ := loop.Prepare(ai.JSON(`{"prompt":"check deployment"}`))
	store, _ := continuation.NewMemoryStore()
	engine, _ := continuation.New(store, continuation.WithClock(clock))
	workerRef := continuation.HandlerRef{Kind: "deployment-check", Version: "v1"}
	controllerRef := continuation.HandlerRef{Kind: "fixed-loop", Version: "v1"}
	execution, _ := engine.Create(context.Background(), continuation.CreateRequest{
		ID: "deployment-loop", Target: continuation.Target{Kind: "session", ID: "deploy-1"},
		Worker: workerRef, Controller: controllerRef,
		ControllerState: setup.ControllerState, Input: setup.WorkInput,
	})

	waiting, _ := engine.Advance(context.Background(), execution.ID, execution.Revision, continuation.Handlers{
		WorkerRef: workerRef,
		Worker: exampleWorker(func(context.Context, continuation.WorkRequest) (continuation.WorkResult, error) {
			return continuation.WorkResult{
				Value: ai.JSON(`{"status":"running"}`), Progress: continuation.ProgressChanged,
			}, nil
		}),
		ControllerRef: controllerRef, Controller: controller,
	})
	clock.now = clock.now.Add(5 * time.Minute)
	ready, _ := engine.ResumeDue(context.Background(), waiting.ID, waiting.Revision)

	fmt.Println(waiting.Status, ready.Status)
}
Output:
waiting ready

func NewController

func NewController(planner Planner, options ...ControllerOption) (*Controller, error)

NewController constructs a Loop Controller.

func (*Controller) Decide

func (controller *Controller) Decide(
	ctx context.Context,
	request continuation.DecisionRequest,
) (continuation.Decision, error)

Decide implements continuation.Controller.

type ControllerOption

type ControllerOption func(*controllerConfig) error

ControllerOption configures a Loop Controller.

func WithClock

func WithClock(clock continuation.Clock) ControllerOption

WithClock replaces the Decision-time clock.

type ModelPlanner

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

ModelPlanner chooses bounded dynamic delays with one structured model call and no tools.

func NewModelPlanner

func NewModelPlanner(
	model ai.LanguageModel,
	options ...ModelPlannerOption,
) (*ModelPlanner, error)

NewModelPlanner constructs a provider-neutral dynamic Planner.

func (*ModelPlanner) Plan

func (planner *ModelPlanner) Plan(ctx context.Context, request PlanRequest) (Plan, error)

Plan implements Planner.

type ModelPlannerOption

type ModelPlannerOption func(*modelPlannerConfig) error

ModelPlannerOption configures a ModelPlanner.

func WithDelayBounds

func WithDelayBounds(minimum, maximum time.Duration) ModelPlannerOption

WithDelayBounds sets inclusive dynamic delay bounds. Both values must be positive whole seconds.

func WithMaxTokens

func WithMaxTokens(maxTokens int) ModelPlannerOption

WithMaxTokens bounds one planner response.

type Plan

type Plan struct {
	Stop          bool
	After         time.Duration
	SignalKey     string
	Reason        string
	PlannerState  ai.JSON
	NextWorkInput ai.JSON
	Output        ai.JSON
	Usage         ai.Usage
}

Plan selects the next activation or stops the Loop.

type PlanRecord

type PlanRecord struct {
	Stop      bool          `json:"stop"`
	After     time.Duration `json:"after,omitempty"`
	SignalKey string        `json:"signal_key,omitempty"`
	Reason    string        `json:"reason"`
}

PlanRecord is the bounded durable projection of one activation plan.

type PlanRequest

type PlanRequest struct {
	Iteration    int
	WorkInput    ai.JSON
	Evidence     ai.JSON
	PlannerState ai.JSON
	Attempt      int
	Activation   *continuation.Activation
	Limits       continuation.Limits
	Accounting   continuation.Accounting
	Previous     *PlanRecord
}

PlanRequest is the immutable input for planning after one Work iteration.

type Planner

type Planner interface {
	Plan(context.Context, PlanRequest) (Plan, error)
}

Planner selects when another Loop iteration should become runnable.

type PlannerFunc

type PlannerFunc func(context.Context, PlanRequest) (Plan, error)

PlannerFunc adapts a function to Planner.

func (PlannerFunc) Plan

func (function PlannerFunc) Plan(ctx context.Context, request PlanRequest) (Plan, error)

Plan implements Planner.

type Setup

type Setup struct {
	ControllerState ai.JSON
	WorkInput       ai.JSON
}

Setup contains the durable state and first Worker input for a Loop execution.

func Prepare

func Prepare(input ai.JSON) (Setup, error)

Prepare validates and persists the stable input for a new Loop.

type State

type State struct {
	Version      int         `json:"version"`
	Iterations   int         `json:"iterations"`
	WorkInput    ai.JSON     `json:"input,omitempty"`
	PlannerState ai.JSON     `json:"planner_state,omitempty"`
	Last         *PlanRecord `json:"last,omitempty"`
}

State is the versioned Loop projection stored as continuation ControllerState.

func DecodeState

func DecodeState(data ai.JSON) (State, error)

DecodeState validates and decodes Loop ControllerState.

Jump to

Keyboard shortcuts

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