interleavedthinking

package
v0.1.0 Latest Latest
Warning

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

Go to latest
Published: Oct 5, 2026 License: Apache-2.0 Imports: 13 Imported by: 0

Documentation

Index

Constants

View Source
const (
	DefaultStreamToClient       = "hidden"
	DefaultRegularTurns         = 2
	DefaultMaxMemoBytes         = 16 * 1024
	DefaultMaxInstructionsBytes = 64 * 1024
)

Default values for interleaved thinking configuration.

View Source
const (
	MemoOpenTag  = "<proxy_thinker_memo>"
	MemoCloseTag = "</proxy_thinker_memo>"

	// ExtractionSourceFull marks a memo captured as the full bounded thinker
	// output. Whole-output capture is the only extraction path since memo
	// wrapper tags were removed from the thinker prompt.
	ExtractionSourceFull = "full"
)

Memo wrapper tags are no longer required or prompted for. They are tolerated defensively: complete wrapper tags are stripped from the stored memo and from the visible stream in case a model still emits them from cached prompts.

View Source
const DefaultInstructions = `` /* 2226-byte string literal not displayed */

DefaultInstructions is the built-in thinker prompt used when instructions_file is empty.

View Source
const ID = "interleaved-thinking"

ID is the canonical feature identifier in plugins.features.

View Source
const MemoInjectionModeConversationView = "conversation_view_overlay"

MemoInjectionModeConversationView identifies the memo injection mode in diagnostics.

View Source
const MemoOverlayID = "interleaved-thinking-memo"

MemoOverlayID is the stable conversation-view overlay ID that carries the latest thinker memo for an A-leg. Each capture replaces the payload and re-resolves the anchor to the current ingress tail.

View Source
const MemoSteeringReason = "interleaved_thinking_memo"

MemoSteeringReason is the bounded content-free reason recorded on the memo steering overlay and its diagnostics.

View Source
const SessionSteeringGuidanceHeader = "[Session Steering Guidance]"

SessionSteeringGuidanceHeader is the plain-text header that introduces the steering block. It is used when persisting the thinker memo as a conversation-view steering overlay.

Variables

View Source
var (
	// ErrMemoNotFound is returned when a memo reference does not exist under
	// the requested scope. Cross-scope access must surface this error so
	// session isolation is enforced by the store contract.
	ErrMemoNotFound = errors.New("interleavedthinking: memo not found")
	// ErrMemoTooLarge is returned when a put or update would store memo content
	// exceeding the configured byte limit.
	ErrMemoTooLarge = errors.New("interleavedthinking: memo too large")
	// ErrEmptyScope is returned when a mutating or lookup operation is called
	// with an empty scope. An empty scope cannot own a memo.
	ErrEmptyScope = errors.New("interleavedthinking: empty scope")
	// ErrEmptyMemoRef is returned when a mutating or lookup operation is called
	// with a memo reference whose key is empty. Lookup is keyed by ref.Key, so
	// an empty key cannot identify a memo.
	ErrEmptyMemoRef = errors.New("interleavedthinking: empty memo ref")
)

Sentinel errors for the memo store contract.

View Source
var ErrThinkerInstructionsMissing = errors.New("interleavedthinking: thinker instructions required but missing")

ErrThinkerInstructionsMissing is returned when a thinker candidate is shaped without resolved thinker instructions.

Functions

func IsMemoOverlay

func IsMemoOverlay(id string) bool

IsMemoOverlay reports whether id identifies the thinker-memo steering overlay, so generic orchestration can filter it without knowing the policy.

func MemoPutRequest

func MemoPutRequest(memo string) steering.PutRequest

MemoPutRequest builds the trusted steering mutation that persists or replaces the thinker memo overlay for an A-leg. Placement resolves after_ingress_tail against the accepted ingress trajectory frozen at turn preparation; the anchor therefore stays fixed while later history appends behind it (cache-stable).

func RenderMemoPayload

func RenderMemoPayload(memo string) string

RenderMemoPayload renders the model-visible user-message text persisted for a captured memo. The header keeps prior injections unambiguous without any protocol-specific markers.

func ResolveInstructions

func ResolveInstructions(baseDir string, path string, inline string) (string, error)

ResolveInstructions returns the thinker instructions text. When path is non-empty, it validates the path and reads the file bounded by maxBytes. When path is empty, inline is returned if non-empty, otherwise DefaultInstructions is returned.

func ShapeExecutorCall

func ShapeExecutorCall(
	ctx context.Context,
	call lipapi.Call,
	store MemoStore,
	scope Scope,
	ref *state.MemoRef,
	suppressVisibleMemo bool,
) (lipapi.Call, bool, *PendingMemoUpdate, MemoOutcome, error)

ShapeExecutorCall classifies the latest valid memo for an executor candidate, applies budget decrements, and validates the call.

func ShapeThinkerCall

func ShapeThinkerCall(call lipapi.Call, instructions string) (lipapi.Call, error)

ShapeThinkerCall shapes a thinker candidate call by prepending thinker instructions to Instructions, clearing Tools and ToolChoice, and validating.

func StripResidualMemoTags

func StripResidualMemoTags(text string) string

StripResidualMemoTags removes complete <proxy_thinker_memo> and </proxy_thinker_memo> wrapper tags from text. It is a defensive cleanup for models that still emit wrapper tags from cached prompts; the tags are never required or prompted for. Matching is case-insensitive, treats a tag name followed by a boundary (whitespace, '/' or '>') as a tag, and preserves incomplete tag fragments as literal content.

Types

type Config

type Config struct {
	Enabled               bool   `yaml:"enabled"`
	InstructionsFile      string `yaml:"instructions_file"`
	Instructions          string `yaml:"instructions"`
	StreamToClient        string `yaml:"stream_to_client"`
	RegularTurnsRemaining int    `yaml:"regular_turns_remaining"`
	MaxMemoBytes          int    `yaml:"max_memo_bytes"`
}

Config carries operator-supplied settings for interleaved thinking.

func DecodeConfig

func DecodeConfig(n yaml.Node) (Config, error)

DecodeConfig decodes a feature-private YAML subtree into Config.

func (Config) EffectiveMaxMemoBytes

func (c Config) EffectiveMaxMemoBytes() int

EffectiveMaxMemoBytes returns the configured memo size limit or default when <= 0.

func (Config) EffectiveRegularTurnsRemaining

func (c Config) EffectiveRegularTurnsRemaining() int

EffectiveRegularTurnsRemaining returns the configured budget or default when <= 0.

func (Config) EffectiveStreamToClient

func (c Config) EffectiveStreamToClient() string

EffectiveStreamToClient returns the visibility mode, defaulting to hidden when unset.

func (*Config) Validate

func (c *Config) Validate() error

Validate applies defaults and validates settings when enabled.

type InMemoryMemoStore

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

InMemoryMemoStore is a process-local, bounded MemoStore keyed by scope and memo reference. It is safe for concurrent use.

func NewMemoStore

func NewMemoStore(maxBytes int) *InMemoryMemoStore

NewMemoStore returns an in-memory memo store that rejects memo content larger than maxBytes. A non-positive maxBytes disables size enforcement.

func (*InMemoryMemoStore) Delete

func (s *InMemoryMemoStore) Delete(ctx context.Context, scope Scope, ref state.MemoRef) error

Delete removes the memo stored under scope for ref.Key.

func (*InMemoryMemoStore) Get

Get returns the memo state stored under scope for ref.Key.

func (*InMemoryMemoStore) Latest

func (s *InMemoryMemoStore) Latest(ctx context.Context, scope Scope) (state.MemoState, bool, error)

Latest returns the most recent memo state stored under scope, if any.

func (*InMemoryMemoStore) LatestEntry

func (s *InMemoryMemoStore) LatestEntry(ctx context.Context, scope Scope) (state.MemoState, state.MemoRef, bool, error)

LatestEntry returns the most recent memo state and reference stored under scope, if any.

func (*InMemoryMemoStore) Put

Put stores a new memo under scope, allocates a new reference key with Version=1, and returns the allocated reference.

func (*InMemoryMemoStore) Update

func (s *InMemoryMemoStore) Update(ctx context.Context, scope Scope, ref state.MemoRef, st state.MemoState) (state.MemoRef, error)

Update replaces the memo state stored under scope for ref.Key, bumps Version, and returns the updated reference.

type MemoOutcome

type MemoOutcome string

MemoOutcome classifies executor memo shaping for bounded diagnostics.

const (
	MemoOutcomeNone           MemoOutcome = ""
	MemoOutcomeInjected       MemoOutcome = "injected"
	MemoOutcomeExpired        MemoOutcome = "expired"
	MemoOutcomeSkippedVisible MemoOutcome = "skipped_visible"
	MemoOutcomeSkippedMissing MemoOutcome = "skipped_missing"
	MemoOutcomeSkippedEmpty   MemoOutcome = "skipped_empty"
)

type MemoRef

type MemoRef = state.MemoRef

MemoRef aliases state.MemoRef for convenience.

type MemoResult

type MemoResult struct {
	Text       string
	Reference  string
	Version    int64
	HadContent bool
}

MemoResult carries minimal evidence of captured thinker output.

type MemoState

type MemoState = state.MemoState

MemoState aliases state.MemoState for convenience.

type MemoStore

type MemoStore interface {
	Put(ctx context.Context, scope Scope, st state.MemoState) (state.MemoRef, error)
	Get(ctx context.Context, scope Scope, ref state.MemoRef) (state.MemoState, bool, error)
	Update(ctx context.Context, scope Scope, ref state.MemoRef, st state.MemoState) (state.MemoRef, error)
	Delete(ctx context.Context, scope Scope, ref state.MemoRef) error
	LatestEntry(ctx context.Context, scope Scope) (state.MemoState, state.MemoRef, bool, error)
}

MemoStore is the bounded memo store contract keyed by memo reference under an authoritative scope.

type PendingMemoUpdate

type PendingMemoUpdate struct {
	Ref   state.MemoRef
	State state.MemoState
}

PendingMemoUpdate is the memo-store mutation that should be committed once a shaped executor attempt becomes authoritative.

type Processor

type Processor interface {
	BeginTurn(ctx context.Context, in TurnInput) (Turn, error)
	IsMemoVisibleToClient(ctx context.Context, aLegID string) bool
}

Processor is the feature-owned entry point for interleaved thinking per turn.

func NewProcessor

func NewProcessor(cfg Config, store MemoStore) (Processor, error)

NewProcessor constructs a feature-owned Processor.

type Recorder

type Recorder struct {
	MaxMemoBytes int

	// Identity metadata copied into the resulting MemoState.
	SourceSelector        string
	Backend               string
	Model                 string
	RequestID             string
	RegularTurnsRemaining int
	// contains filtered or unexported fields
}

Recorder observes canonical thinker stream events, captures the entire thinker output as a bounded memo, and produces a bounded MemoState at stream completion.

Observe also sanitizes the visible stream: residual memo wrapper tags are stripped (including across delta boundaries) and thinker content is emitted as canonical EventReasoningDelta so wrapper tags never surface as ordinary assistant text. The stored memo is bounded by MaxMemoBytes; a zero MaxMemoBytes disables bounding, matching the memo store convention.

Identity metadata fields are set by the caller before Finish and copied into the resulting MemoState. Injection metadata (InjectedCount, VisibleToClient) is left zero at capture time.

func (*Recorder) Finish

func (r *Recorder) Finish(interrupted bool) state.MemoState

Finish returns the captured MemoState. The memo is the complete bounded thinker output with residual wrapper tags stripped, trimmed of surrounding whitespace. interrupted marks the stored memo as captured from an interrupted stream.

func (*Recorder) FlushVisibleSanitizer

func (r *Recorder) FlushVisibleSanitizer() []lipapi.Event

FlushVisibleSanitizer returns any buffered partial-tag visible content and should be called once at stream end before Finish when surfacing thinker output.

func (*Recorder) HadContent

func (r *Recorder) HadContent() bool

HadContent reports whether any non-empty content delta was observed. It lets callers distinguish an empty memo (content observed, nothing extractable after normalization) from a stream that never produced content at all.

func (*Recorder) Observe

func (r *Recorder) Observe(ev lipapi.Event) []lipapi.Event

Observe processes one canonical event: it feeds text/reasoning deltas to memo capture and returns sanitized visible events. Returned content deltas are always EventReasoningDelta with residual memo wrapper tags stripped. Non-content events pass through unchanged; call FlushVisibleSanitizer at stream end to emit any buffered partial-tag visible content.

type Scope

type Scope string

Scope identifies the authoritative session or A-leg that owns a memo. Memos

type Turn

type Turn interface {
	ShapeThinker(call lipapi.Call) (lipapi.Call, error)
	ObserveThinkerEvent(ev lipapi.Event) ([]lipapi.Event, error)
	FinalizeThinker(ctx context.Context) (MemoResult, error)
	FinalizeThinkerStatus(ctx context.Context, interrupted bool, visibleCommitted bool) (MemoResult, error)
	ShapeExecutor(ctx context.Context, call lipapi.Call, memo MemoResult) (lipapi.Call, error)
	Visible() bool
	CanContinue() bool
	ShapeDiagnostics() (outcome string, turnsRemaining int)
	CommitExecutor(ctx context.Context) (int, error)
	FlushVisible() []lipapi.Event
}

Turn is the feature-owned lifecycle contract for a single turn.

type TurnInput

type TurnInput struct {
	ALegID              string
	Selector            string
	Backend             string
	Model               string
	RequestID           string
	StreamToClient      string
	SuppressVisibleMemo bool
}

TurnInput carries per-turn facts required by interleaved thinking.

Directories

Path Synopsis

Jump to

Keyboard shortcuts

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