orchestrator

package
v0.0.8 Latest Latest
Warning

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

Go to latest
Published: Mar 4, 2026 License: GPL-3.0 Imports: 11 Imported by: 0

Documentation

Overview

Package orchestrator provides an agent.Router implementation that manages NPC agents within a Glyphoxa session. It adds address detection, cross-NPC awareness, and DM override capabilities on top of the base agent.Router contract.

Index

Constants

This section is empty.

Variables

View Source
var ErrNoTarget = errors.New("orchestrator: no target NPC identified")

ErrNoTarget is returned when address detection cannot determine which NPC was addressed by a player's utterance.

Functions

This section is empty.

Types

type AddressDetector

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

AddressDetector determines which NPC was spoken to by scanning the transcript text for NPC names, falling back through a priority chain of heuristics (DM override → last-speaker continuation → single-NPC fallback).

func NewAddressDetector

func NewAddressDetector(agents []agent.NPCAgent) *AddressDetector

NewAddressDetector builds a name index from the given agents.

The index includes the full lowercase name of each NPC and every individual word of length ≥ 3 from that name. For example, "Grimjaw the Blacksmith" produces entries for "grimjaw the blacksmith", "grimjaw", and "blacksmith" (the word "the" is too short).

func (*AddressDetector) Detect

func (d *AddressDetector) Detect(
	text string,
	lastSpeaker string,
	activeAgents map[string]*agentEntry,
	dmOverrides map[string]string,
	speaker string,
) (string, error)

Detect returns the agent ID of the NPC addressed in the transcript.

The detection strategy is applied in order:

  1. Explicit name match — scan text for indexed NPC names/fragments.
  2. DM override — if speaker has an active puppet override in dmOverrides.
  3. Last-speaker continuation — route to lastSpeaker if set and active.
  4. Single-NPC fallback — if exactly one unmuted NPC exists, route there.
  5. No match — return ("", ErrNoTarget).

func (*AddressDetector) Rebuild

func (d *AddressDetector) Rebuild(agents []agent.NPCAgent)

Rebuild rebuilds the name index from a fresh set of agents. Call this after adding or removing agents.

type BufferEntry

type BufferEntry struct {
	// SpeakerID identifies the speaker (player user-ID or NPC agent ID).
	SpeakerID string

	// SpeakerName is the human-readable name of the speaker.
	SpeakerName string

	// Text is the utterance text.
	Text string

	// NPCID is non-empty when the utterance was produced by an NPC agent.
	NPCID string

	// Timestamp records when the utterance occurred.
	Timestamp time.Time
}

BufferEntry represents a single utterance stored in the UtteranceBuffer.

type Option

type Option func(*Orchestrator)

Option configures an Orchestrator during construction.

func WithBufferDuration

func WithBufferDuration(d time.Duration) Option

WithBufferDuration sets the maximum age of entries in the cross-NPC utterance buffer. The default is 5 minutes.

func WithBufferSize

func WithBufferSize(n int) Option

WithBufferSize sets the maximum number of entries retained in the cross-NPC utterance buffer. The default is 20.

type Orchestrator

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

Orchestrator manages NPC agents within a Glyphoxa session. It implements agent.Router and adds lifecycle management, address detection, cross-NPC awareness, and DM override capabilities.

All exported methods are safe for concurrent use.

func New

func New(agents []agent.NPCAgent, opts ...Option) *Orchestrator

New creates an Orchestrator with the given NPC agents and functional options.

Each agent must have a unique agent.NPCAgent.ID; duplicates are silently dropped (last one wins). Passing a nil or empty agents slice is valid and results in an orchestrator with no active agents.

func (*Orchestrator) ActiveAgents

func (o *Orchestrator) ActiveAgents() []agent.NPCAgent

ActiveAgents returns a snapshot of all NPC agents currently managed by this orchestrator, including both muted and unmuted agents.

func (*Orchestrator) AddAgent

func (o *Orchestrator) AddAgent(a agent.NPCAgent) error

AddAgent registers a new NPC agent with the orchestrator. Returns an error if an agent with the same ID is already registered.

func (*Orchestrator) AgentByName added in v0.0.3

func (o *Orchestrator) AgentByName(name string) agent.NPCAgent

AgentByName returns the first agent whose Name() matches name (case-insensitive). Returns nil if no match is found.

func (*Orchestrator) BroadcastScene

func (o *Orchestrator) BroadcastScene(ctx context.Context, scene agent.SceneContext) error

BroadcastScene pushes a scene update to all active (unmuted) agents. Errors from individual agents are collected; all agents are attempted regardless of individual failures. If multiple agents fail, the returned error is a joined error containing one wrapped error per failing agent.

func (*Orchestrator) IsMuted added in v0.0.3

func (o *Orchestrator) IsMuted(id string) (bool, error)

IsMuted reports whether the agent with the given ID is muted. Returns an error if id does not correspond to a registered agent.

func (*Orchestrator) MuteAgent

func (o *Orchestrator) MuteAgent(id string) error

MuteAgent prevents the agent identified by id from receiving new utterances. Returns an error if id does not correspond to a registered agent.

func (*Orchestrator) MuteAll added in v0.0.3

func (o *Orchestrator) MuteAll() int

MuteAll mutes all agents atomically and returns the number of agents whose mute state was changed (agents already muted are not counted).

func (*Orchestrator) RemoveAgent

func (o *Orchestrator) RemoveAgent(id string) error

RemoveAgent unregisters an NPC agent. Returns an error if not found.

func (*Orchestrator) Route

func (o *Orchestrator) Route(ctx context.Context, speaker string, transcript stt.Transcript) (agent.NPCAgent, error)

Route determines which agent.NPCAgent was addressed by speaker's utterance and returns that agent. Before returning, Route injects recent cross-NPC utterances into the target agent's engine via engine.VoiceEngine.InjectContext.

If no NPC can be identified or the identified NPC is muted, Route returns ErrNoTarget.

func (*Orchestrator) SetPuppet

func (o *Orchestrator) SetPuppet(speaker string, npcID string) error

SetPuppet forces all utterances from speaker to be routed to the NPC identified by npcID, bypassing address detection. Use for DM puppeteering.

Pass an empty npcID to clear the override for that speaker. Returns an error if npcID is non-empty and does not correspond to a registered agent.

func (*Orchestrator) UnmuteAgent

func (o *Orchestrator) UnmuteAgent(id string) error

UnmuteAgent re-enables routing to the agent identified by id. Returns an error if id does not correspond to a registered agent. Calling UnmuteAgent on an already-unmuted agent is a no-op.

func (*Orchestrator) UnmuteAll added in v0.0.3

func (o *Orchestrator) UnmuteAll() int

UnmuteAll unmutes all agents atomically and returns the number of agents whose mute state was changed (agents already unmuted are not counted).

type UtteranceBuffer

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

UtteranceBuffer maintains a shared buffer of recent utterances from all NPCs and players. Each NPC can read from this buffer to understand what other NPCs have said recently (cross-NPC awareness).

The buffer enforces both a maximum entry count and a maximum age. Entries that exceed either limit are evicted automatically on every [Add] call.

All methods are safe for concurrent use.

func NewUtteranceBuffer

func NewUtteranceBuffer(maxSize int, maxAge time.Duration) *UtteranceBuffer

NewUtteranceBuffer creates a buffer that retains at most maxSize entries and evicts entries older than maxAge.

func (*UtteranceBuffer) Add

func (b *UtteranceBuffer) Add(entry BufferEntry)

Add appends an entry to the buffer and evicts entries that exceed the configured maximum size or age.

func (*UtteranceBuffer) Entries

func (b *UtteranceBuffer) Entries() []BufferEntry

Entries returns all current buffer entries in chronological order. Intended for testing and debugging.

func (*UtteranceBuffer) Recent

func (b *UtteranceBuffer) Recent(excludeNPCID string, maxEntries int) []BufferEntry

Recent returns up to maxEntries entries that are within the configured maxAge window, excluding any entries whose NPCID matches excludeNPCID. This allows an NPC to see what other NPCs and players have said without seeing its own utterances as "cross-NPC" context.

Entries are returned in chronological order (oldest first).

Jump to

Keyboard shortcuts

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