config

package
v0.3.0 Latest Latest
Warning

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

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

Documentation

Index

Constants

View Source
const (
	BudgetSourceFlag         = "flag"
	BudgetSourceGlobalConfig = "global_config"
	BudgetSourceBuiltin      = "builtin"
)

Budget sources, as reported by BudgetOr. They name where the effective figure came from, so an operator reading the startup log can tell which of the three settings is in force.

View Source
const (
	ConfigPathKey       = "config_path"
	FieldIDKey          = "field_id"
	FieldTypeKey        = "field_type"
	OptionIDKey         = "option_id"
	FieldIndexKey       = "field_index"
	OptionIndexKey      = "option_index"
	WorkspaceIDKey      = "workspace_id"
	WorkspaceColorKey   = "workspace_color"
	WorkspaceEmojiKey   = "workspace_emoji"
	WorkspaceEmojiLen   = "workspace_emoji_len"
	WorkspaceGroupIDKey = "workspace_group_id"
	GroupMemberKey      = "group_member"
	ExportDatasetKey    = "dataset"
	LLMModelRefKey      = "llm_model"
)

Context keys for error values

View Source
const DefaultEmbeddingModel = "gemini-embedding-2"

DefaultEmbeddingModel is the default Gemini embedding model used when --embedding-model is not specified. The dimension is still controlled per-call via gollem's GenerateEmbedding(ctx, dimension, ...).

Variables

View Source
var (
	ErrConfigNotFound        = goerr.New("configuration file not found")
	ErrInvalidConfig         = goerr.New("invalid configuration")
	ErrDuplicateFieldID      = goerr.New("duplicate field ID")
	ErrDuplicateOptionID     = goerr.New("duplicate option ID")
	ErrInvalidFieldID        = goerr.New("invalid field ID format")
	ErrInvalidFieldType      = goerr.New("invalid field type")
	ErrMissingOptions        = goerr.New("select/multi-select field requires at least one option")
	ErrInvalidMetadata       = goerr.New("invalid metadata format")
	ErrMissingName           = goerr.New("name is required")
	ErrInvalidWorkspaceID    = goerr.New("invalid workspace ID format")
	ErrMissingWorkspaceID    = goerr.New("workspace ID is required")
	ErrDuplicateWorkspaceID  = goerr.New("duplicate workspace ID")
	ErrNoConfigFiles         = goerr.New("no configuration files found")
	ErrInvalidWelcomeMessage = goerr.New("invalid Slack welcome message template")
	// ErrWorkspaceEmojiColorConflict is returned when both emoji and color are
	// set in the [workspace] section. They are mutually exclusive because the
	// UI renders either an emoji badge (neutral background) or a colored
	// initials badge, never both.
	ErrWorkspaceEmojiColorConflict = goerr.New("workspace emoji and color are mutually exclusive")
	// ErrInvalidWorkspaceColor is returned when the [workspace] color is not a
	// 6-digit #RRGGBB hex code.
	ErrInvalidWorkspaceColor = goerr.New("invalid workspace color format")
	// ErrInvalidWorkspaceEmoji is returned when the [workspace] emoji exceeds
	// the allowed rune length.
	ErrInvalidWorkspaceEmoji = goerr.New("invalid workspace emoji")
	ErrInvalidCaseMode       = goerr.New("invalid case mode")
	ErrInvalidCaseTrigger    = goerr.New("invalid case trigger")
	ErrMissingMonitorChannel = goerr.New("thread mode requires [slack] channel")
	ErrInvalidMonitorChannel = goerr.New("invalid Slack channel ID")
	ErrMissingCaseStatus     = goerr.New("thread mode requires [case.status]")
	// ErrReactionRequiresThreadMode is returned when [slack] reaction is set on a
	// workspace that is not in thread mode. Reaction-triggered case creation needs
	// a destination thread, which only thread mode provides.
	ErrReactionRequiresThreadMode = goerr.New("[slack] reaction requires mode = \"thread\"")
	// ErrInvalidReactionEmoji is returned when [slack] reaction, after stripping
	// surrounding colons, is empty or contains characters outside a Slack emoji
	// name.
	ErrInvalidReactionEmoji = goerr.New("invalid Slack reaction emoji name")
	// ErrDuplicateReactionEmoji is returned when the same reaction emoji is
	// configured on more than one workspace, which would make emoji-to-workspace
	// resolution ambiguous.
	ErrDuplicateReactionEmoji = goerr.New("duplicate Slack reaction emoji across workspaces")

	// ErrWorkspaceChannelRequiresChannelMode is returned when workspace_channel is
	// set on a workspace that is not in channel mode. It names a separate channel
	// to host the cross-case agent; a thread-mode workspace already has one — the
	// monitored channel, where a channel-root mention runs that agent — so a
	// second one would only make channel-to-workspace routing ambiguous.
	// [slack.workspace_agent] itself is accepted in both modes.
	ErrWorkspaceChannelRequiresChannelMode = goerr.New("[slack] workspace_channel requires channel mode")
	// ErrMissingWorkspaceChannel is returned when [slack.workspace_agent] is set
	// on a CHANNEL-mode workspace but [slack] workspace_channel is empty: there
	// the agent runs in the workspace channel and is meaningless without it. In
	// thread mode the section stands alone (the monitored channel hosts it).
	ErrMissingWorkspaceChannel = goerr.New("[slack.workspace_agent] requires [slack] workspace_channel")
	// ErrInvalidWorkspaceChannel is returned when [slack] workspace_channel is not
	// a Slack channel ID (e.g. a channel name).
	ErrInvalidWorkspaceChannel = goerr.New("invalid Slack workspace_channel ID")
	// ErrDuplicateWorkspaceChannel is returned when the same channel ID is used as
	// a workspace_channel on more than one workspace, or collides with another
	// workspace's monitored channel, which would make channel-to-workspace routing
	// ambiguous.
	ErrDuplicateWorkspaceChannel = goerr.New("duplicate Slack workspace_channel across workspaces")
	// ErrWorkspaceAgentPromptConflict is returned when [slack.workspace_agent]
	// sets both prompt and prompt_file (mutually exclusive).
	ErrWorkspaceAgentPromptConflict = goerr.New("[slack.workspace_agent] prompt and prompt_file are mutually exclusive")
	// ErrWorkspaceAgentPromptEmpty is returned when [slack.workspace_agent]
	// prompt_file resolves to an empty file.
	ErrWorkspaceAgentPromptEmpty = goerr.New("[slack.workspace_agent] prompt_file is empty")
	// ErrMissingReferenceWorkspace is returned when a case_ref /
	// multi_case_ref field omits reference_workspace.
	ErrMissingReferenceWorkspace = goerr.New("case_ref field requires reference_workspace")
	// ErrUnexpectedReferenceWorkspace is returned when reference_workspace is set
	// on a field whose type is not a case_ref type.
	ErrUnexpectedReferenceWorkspace = goerr.New("reference_workspace is only valid for case_ref fields")
	// ErrUnknownReferenceWorkspace is returned when reference_workspace points at
	// a workspace ID that is not defined across the loaded configs.
	ErrUnknownReferenceWorkspace = goerr.New("reference_workspace points to an unknown workspace")
	// ErrRequiredCaseRefUnsupported is returned when a case_ref / multi_case_ref
	// field is marked required: the Slack case-creation modal cannot collect a
	// case reference, so a required one would make the case un-creatable.
	ErrRequiredCaseRefUnsupported = goerr.New("case_ref fields cannot be required")

	// ErrMissingWorkspaceGroupID is returned when a [[workspace_group]] omits id.
	ErrMissingWorkspaceGroupID = goerr.New("workspace group ID is required")
	// ErrInvalidWorkspaceGroupID is returned when a workspace group id does not
	// match the allowed pattern or exceeds the length limit.
	ErrInvalidWorkspaceGroupID = goerr.New("invalid workspace group ID format")
	// ErrDuplicateWorkspaceGroupID is returned when the same workspace group id
	// is defined more than once across the global config files.
	ErrDuplicateWorkspaceGroupID = goerr.New("duplicate workspace group ID")
	// ErrDuplicateGroupMember is returned when the same workspace id appears more
	// than once in a single group's members list.
	ErrDuplicateGroupMember = goerr.New("duplicate workspace group member")
	// ErrUnknownGroupMember is returned when a group member references a
	// workspace id that is not defined across the loaded workspace configs.
	ErrUnknownGroupMember = goerr.New("workspace group member references an unknown workspace")
	// ErrGlobalConfigContainsWorkspace is returned when a --global-config file
	// contains a [workspace] section. Workspace definitions belong under
	// --config (1 file = 1 workspace); the global config is for deployment-wide
	// settings only, so mixing the two is rejected loudly rather than ignored.
	ErrGlobalConfigContainsWorkspace = goerr.New("global config file must not contain a [workspace] section")

	// ErrInvalidExportConfig is returned when the [export] section is malformed,
	// e.g. a missing [export.bigquery] project.
	ErrInvalidExportConfig = goerr.New("invalid export configuration")
	// ErrInvalidExportDataset is returned when an [[export.bigquery.workspace]]
	// dataset name is not a valid BigQuery dataset ID (BigQuery forbids hyphens).
	ErrInvalidExportDataset = goerr.New("invalid export dataset name")
	// ErrDuplicateExportWorkspace is returned when the same workspace id — or the
	// same dataset name — appears more than once in the export config.
	ErrDuplicateExportWorkspace = goerr.New("duplicate export workspace mapping")
	// ErrUnknownExportWorkspace is returned when an export workspace mapping
	// references a workspace id not defined across the loaded workspace configs.
	ErrUnknownExportWorkspace = goerr.New("export workspace mapping references an unknown workspace")
	// ErrDuplicateExportConfig is returned when more than one global config file
	// defines an [export] section.
	ErrDuplicateExportConfig = goerr.New("duplicate [export] section across global config files")

	// ErrDuplicateAgentConfig is returned when more than one global config file
	// defines an [agent] section. Like [export], the deployment-wide agent
	// settings must have a single home.
	ErrDuplicateAgentConfig = goerr.New("duplicate [agent] section across global config files")
	// ErrInvalidBudget is returned when a configured budget is negative, or so
	// small it rounds away to zero (which would read as "not set").
	ErrInvalidBudget = goerr.New("invalid budget")
	// ErrInvalidLLMModel is returned when an [[llm_model]] entry is malformed,
	// e.g. it names no model.
	ErrInvalidLLMModel = goerr.New("invalid [[llm_model]] entry")
	// ErrInvalidLLMModelRef is returned when a model reference name — an
	// [[llm_model]] alias, or a Job's llm_model — does not match the allowed
	// pattern or exceeds the length limit.
	ErrInvalidLLMModelRef = goerr.New("invalid model reference name")
	// ErrInvalidLLMModelPrice is returned when an [[llm_model]] price is
	// negative, missing where required, or too small to represent.
	ErrInvalidLLMModelPrice = goerr.New("invalid model price")
	// ErrDuplicateLLMModelRef is returned when the same model reference name is
	// defined more than once across the global config files.
	ErrDuplicateLLMModelRef = goerr.New("duplicate model reference name")
	// ErrUnknownLLMModelRef is returned when a Job — or the --llm-model flag —
	// names a model that no [[llm_model]] entry defines.
	ErrUnknownLLMModelRef = goerr.New("model reference name is not defined")
)

Sentinel errors for configuration validation

Functions

func BuildWorkspaceRegistry added in v0.3.0

func BuildWorkspaceRegistry(workspaceConfigs []*WorkspaceConfig) *model.WorkspaceRegistry

BuildWorkspaceRegistry turns parsed workspace configurations into the registry the runtime and the consistency check read. It is separate from Configure so a caller that obtained its configurations from somewhere other than CLI paths (the DB consistency check endpoint, which parses documents out of a request) builds the same registry.

func LoadFieldSchema

func LoadFieldSchema(path string) (*domainConfig.FieldSchema, error)

LoadFieldSchema loads the field schema configuration from a TOML file Returns an error if the file does not exist (config.toml is required)

func LoadLLMModels added in v0.3.0

func LoadLLMModels(paths []string) ([]agentkernel.ModelDef, error)

LoadLLMModels walks the given file/dir paths, parses each .toml as a GlobalConfig, validates every [[llm_model]] section, and rejects duplicate reference names across files. Zero files (an unset --global-config) yields an empty slice with no error — a deployment with no LLM configured is a valid state.

Unlike [export], definitions are a SET and may be spread over several files: two files declaring models do not conflict, and the only collision that matters is a repeated reference name.

func LoadWorkspaceGroups

func LoadWorkspaceGroups(paths []string) ([]*model.WorkspaceGroup, error)

LoadWorkspaceGroups walks the given file/dir paths, parses each .toml as a GlobalConfig, validates every [[workspace_group]] section, and rejects duplicate group IDs across files. It does not know the workspace set; member existence is checked by ConfigureGroups. Zero files (empty paths) yields an empty slice with no error — an unset --global-config is a valid state.

func ValidateJobModels added in v0.3.0

func ValidateJobModels(defs []agentkernel.ModelDef, ws *model.WorkspaceRegistry) error

ValidateJobModels checks that every model a Job names is actually defined.

It is a cross-document check — the Jobs come from --config, the definitions from --global-config — so it cannot live in either document's own Validate. It runs at startup, where a Job pointing at an undefined model must stop the process rather than fail at the hour that Job is due, and in `validate`, where an operator asks the same question without deploying.

Types

type ActionSection

type ActionSection struct {
	Initial string                  `toml:"initial"`
	Closed  []string                `toml:"closed"`
	Status  []ActionStatusConfigRow `toml:"status"`
}

ActionSection represents the [action] section in a TOML config. When omitted (nil), the workspace inherits the default action status set.

type ActionStatusConfigRow

type ActionStatusConfigRow struct {
	ID          string `toml:"id"`
	Name        string `toml:"name"`
	Description string `toml:"description"`
	Color       string `toml:"color"`
	Emoji       string `toml:"emoji"`
}

ActionStatusConfigRow represents a single [[action.status]] entry.

type Agent added in v0.3.0

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

Agent holds the CLI flags for the agentkit-based agent runtime: the budget ceilings every Process runs under, and the worker settings of the in-process Serve loop.

func (*Agent) BudgetOr added in v0.3.0

func (a *Agent) BudgetOr(sec *AgentSection) (pricing.NanoUSD, string, error)

BudgetOr resolves the default budget for one run: the command line first, then the global config's [agent] section, then the built-in figure.

The precedence is deliberate. The deployment-wide intent belongs in the document alongside the model definitions it is spent on, while a temporary change for one environment belongs on the command line — so the narrower setting wins. sec may be nil, which is what a deployment with no [agent] section has.

It lives here rather than at the composition root so the three-way decision is made in ONE place: a second caller resolving it differently is how a run ends up bounded by a figure nobody configured.

func (*Agent) Budgets added in v0.3.0

func (a *Agent) Budgets() (agentkernel.Budgets, error)

Budgets returns the validated ceilings for the kernel.

The root tier carries no spend ceiling here: what a run may spend is money, and the figure is resolved per run from its Job and the deployment default (see BudgetOr).

func (*Agent) Flags added in v0.3.0

func (a *Agent) Flags() []cli.Flag

Flags returns the CLI flags for the agent runtime.

func (*Agent) LogAttrs added in v0.3.0

func (a *Agent) LogAttrs() []slog.Attr

LogAttrs returns log attributes describing the configuration.

func (*Agent) ValidateWorker added in v0.3.0

func (a *Agent) ValidateWorker() error

ValidateWorker enforces the worker settings so a misconfiguration fails at startup rather than as a Serve loop that never claims anything.

func (*Agent) WorkerConcurrency added in v0.3.0

func (a *Agent) WorkerConcurrency() int

WorkerConcurrency returns the hard limit on concurrently driven claims.

func (*Agent) WorkerLease added in v0.3.0

func (a *Agent) WorkerLease() time.Duration

WorkerLease returns the configured claim lease duration.

func (*Agent) WorkerPollConcurrency added in v0.3.0

func (a *Agent) WorkerPollConcurrency() int

WorkerPollConcurrency returns the number of poll loops.

func (*Agent) WorkerPollInterval added in v0.3.0

func (a *Agent) WorkerPollInterval() time.Duration

WorkerPollInterval returns the configured poll interval.

type AgentSection added in v0.3.0

type AgentSection struct {
	// DefaultBudgetUSD is what one agent run may spend when neither the Job nor
	// the command line says otherwise. Zero means "not set here".
	DefaultBudgetUSD float64 `toml:"default_budget_usd"`
}

AgentSection is the [agent] section of a global config file: the deployment-wide agent settings that belong in a document rather than on the command line. Nil when no global config declares it.

func LoadAgentSection added in v0.3.0

func LoadAgentSection(paths []string) (*AgentSection, error)

LoadAgentSection walks the given file/dir paths and returns the single [agent] section found. It returns (nil, nil) when no file declares one, and an error when more than one does — the deployment-wide agent settings must have a single home, exactly as [export] does.

func (*AgentSection) DefaultBudget added in v0.3.0

func (s *AgentSection) DefaultBudget() pricing.NanoUSD

DefaultBudget returns the configured budget, or 0 when the section sets none.

func (*AgentSection) Validate added in v0.3.0

func (s *AgentSection) Validate() error

Validate checks the value range only. Zero is a legitimate "not set", so it is accepted; a negative figure is not, and neither is one so small it rounds away to nothing (which would read as "not set" and silently hand the run the built-in default).

type AppConfig

type AppConfig struct {
	Workspace WorkspaceBaseConfig `toml:"workspace"`
	Labels    Labels              `toml:"labels"`
	Fields    []FieldDefinition   `toml:"fields"`
	Slack     SlackSection        `toml:"slack"`
	Compile   CompileSection      `toml:"compile"`
	Assist    AssistSection       `toml:"assist"`
	Action    *ActionSection      `toml:"action"`
	Case      *CaseSection        `toml:"case"`
	Memo      *MemoSection        `toml:"memo"`
	Jobs      []JobSection        `toml:"job"`
}

AppConfig represents the application configuration. It holds TOML-parsed fields and provides CLI Flags()/Configure() methods.

func (*AppConfig) Configure

Configure loads workspace configs from CLI-provided paths and builds a WorkspaceRegistry. It reads "config" from the cli.Command since StringSliceFlag does not support Destination.

func (*AppConfig) ConfigureAgentSection added in v0.3.0

func (a *AppConfig) ConfigureAgentSection(c *cli.Command) (*AgentSection, error)

ConfigureAgentSection reads the --global-config flag and loads the [agent] section, or (nil, nil) when none is declared.

func (*AppConfig) ConfigureExport

func (a *AppConfig) ConfigureExport(c *cli.Command, ws *model.WorkspaceRegistry) (*ExportSection, error)

ConfigureExport reads the --global-config flag, loads the [export] section, and validates it against the workspace registry. It returns (nil, nil) when no [export] is configured (the export subcommand then errors out with a clear message). It mirrors ConfigureGroups so callers that do not export are untouched.

func (*AppConfig) ConfigureGroups

ConfigureGroups reads the --global-config flag, loads workspace groups, and cross-checks every member against the workspace registry. It returns a never-nil registry: an unset flag yields an empty registry (feature dormant). It is a separate method from Configure so the callers that do not need groups (assist / diagnosis / job runtime) are untouched.

func (*AppConfig) ConfigureLLMModels added in v0.3.0

func (a *AppConfig) ConfigureLLMModels(c *cli.Command) ([]agentkernel.ModelDef, error)

ConfigureLLMModels reads the --global-config flag and loads every model definition. It mirrors ConfigureGroups / ConfigureExport so callers that do not need models are untouched.

func (*AppConfig) Flags

func (a *AppConfig) Flags() []cli.Flag

Flags returns CLI flags for workspace configuration.

func (*AppConfig) GlobalConfigFlags added in v0.3.0

func (a *AppConfig) GlobalConfigFlags() []cli.Flag

GlobalConfigFlags returns the --global-config flag on its own, for a command that reads deployment-wide settings but loads no workspace configs. The eval harness needs the model definitions ([[llm_model]]) while taking its scenarios as positional arguments.

func (*AppConfig) ToDomainFieldSchema

func (a *AppConfig) ToDomainFieldSchema() *domainConfig.FieldSchema

ToDomainFieldSchema converts AppConfig to domain FieldSchema

func (*AppConfig) ToDomainMemoConfig

func (a *AppConfig) ToDomainMemoConfig() *domainConfig.MemoConfig

ToDomainMemoConfig converts the [memo] section to a domain MemoConfig. Returns nil when [memo] is omitted, leaving the memo feature disabled for the workspace.

func (*AppConfig) Validate

func (a *AppConfig) Validate() error

Validate checks if the AppConfig is valid

type Archive added in v0.3.0

type Archive struct {
	// History is the per-session gollem history store used by the pre-agentkit
	// agent runtime.
	History gollem.HistoryRepository
	// Trace is where each agent run's archive is written.
	Trace trace.Repository
	// ProcessHistory is the agentkit HistoryStore: one immutable version per
	// committed transition, so a Process's conversation rolls back with its
	// state.
	ProcessHistory agentkit.HistoryStore
	// Close releases the shared storage client and must be called on shutdown.
	Close func()
}

Archive bundles the Cloud Storage-backed stores the agent runtime writes to. They share one client, which Close releases.

type AssistSection

type AssistSection struct {
	Prompt   string `toml:"prompt"`
	Language string `toml:"language"`
}

AssistSection represents the [assist] section in a TOML config

type CaseEventSection

type CaseEventSection struct {
	On []string `toml:"on"`
}

CaseEventSection is the filter for `events.case`. The TOML `on` field is always an array; we deliberately do not accept a single string so the schema stays type-safe.

type CasePromptsSection

type CasePromptsSection struct {
	Create string `toml:"create"`
}

CasePromptsSection represents the [case.prompts] sub-table: workspace- specific additional prompts for the case agent, keyed by lifecycle phase. Only `create` (the thread-mode initialization agent) is consumed today; `mention` / `close` are reserved for future phases.

type CaseSection

type CaseSection struct {
	Initial string                  `toml:"initial"`
	Closed  []string                `toml:"closed"`
	Status  []ActionStatusConfigRow `toml:"status"`
	Prompts CasePromptsSection      `toml:"prompts"`
}

CaseSection represents the [case] section in a TOML config. It mirrors [action] but configures the status set that attaches to Cases in thread mode. It is required for thread-mode workspaces and ignored otherwise.

type CompileSection

type CompileSection struct {
	Prompt string `toml:"prompt"`
}

CompileSection represents the [compile] section in a TOML config

type Embedding

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

Embedding holds CLI configuration for the embedding client. Embedding is always backed by Gemini; chat completion has its own LLM configuration (config.LLM) that may use a different provider entirely.

func (*Embedding) Flags

func (x *Embedding) Flags() []cli.Flag

Flags returns CLI flags for Embedding configuration.

func (*Embedding) IsEnabled

func (x *Embedding) IsEnabled() bool

IsEnabled reports whether the embedding client has the minimum configuration required to be constructed. The CLI commands all require embedding to be enabled; the helper exists so callers can fail fast with a clear message before reaching NewClient.

func (*Embedding) LogAttrs

func (x *Embedding) LogAttrs() []slog.Attr

LogAttrs returns log attributes describing the embedding configuration. Project ID, location, and model name are surfaced; no secret values exist to leak (Application Default Credentials are used by the Gemini SDK).

func (*Embedding) NewClient

func (x *Embedding) NewClient(ctx context.Context) (interfaces.EmbedClient, error)

NewClient builds an interfaces.EmbedClient backed by a dedicated Gemini client. Returns an error when --embedding-gemini-project-id is missing.

type ExportBigQuerySection

type ExportBigQuerySection struct {
	// Project is the destination GCP project ID. Required.
	Project string `toml:"project"`
	// Location is the BigQuery location (e.g. "US", "asia-northeast1") used when a
	// dataset must be created. Optional.
	Location string `toml:"location"`
	// Workspaces maps each exported workspace to its destination dataset. A
	// workspace not listed here is not exported.
	Workspaces []ExportWorkspaceMapping `toml:"workspace"`
}

ExportBigQuerySection configures the BigQuery export sink.

type ExportSection

type ExportSection struct {
	// IncludePrivate is the default for every workspace: when true, private Cases
	// (and their Actions / Memos) are exported too. Defaults to false — private
	// data is NOT exported unless explicitly opted in. A per-workspace mapping may
	// override it.
	IncludePrivate bool `toml:"include_private"`
	// BigQuery is the BigQuery sink configuration. Required (the only sink today).
	BigQuery *ExportBigQuerySection `toml:"bigquery"`
}

ExportSection represents the [export] section of a global config file: the deployment-wide configuration for the `export` subcommand. Nil when no global config declares [export] (the feature is then unavailable).

func LoadExportConfig

func LoadExportConfig(paths []string) (*ExportSection, error)

LoadExportConfig walks the given file/dir paths, parses each .toml as a GlobalConfig, and returns the single [export] section found. It returns (nil, nil) when no file declares [export], and an error when more than one does (the export config must have a single home). A stray [workspace] section is rejected, mirroring LoadWorkspaceGroups. Structural validation against the workspace registry is done by ConfigureExport, not here.

func (*ExportSection) IncludePrivateFor

func (s *ExportSection) IncludePrivateFor(m ExportWorkspaceMapping) bool

IncludePrivateFor returns the effective include_private for a mapping: the mapping's own value when set, otherwise the section-level default.

func (*ExportSection) Validate

func (s *ExportSection) Validate(ws *model.WorkspaceRegistry) error

Validate checks the export section against the workspace registry: BigQuery project presence, dataset-name validity, uniqueness of workspace ids and dataset names, and existence of every referenced workspace.

type ExportWorkspaceMapping

type ExportWorkspaceMapping struct {
	// ID is the workspace ID (must exist in the workspace registry).
	ID string `toml:"id"`
	// Dataset is the destination BigQuery dataset name. BigQuery dataset names
	// forbid hyphens, so this is given explicitly rather than derived from ID.
	Dataset string `toml:"dataset"`
	// IncludePrivate overrides the section-level default for this workspace when
	// set (non-nil). Nil means "inherit [export].include_private".
	IncludePrivate *bool `toml:"include_private"`
}

ExportWorkspaceMapping maps one workspace to a BigQuery dataset.

type FieldDefinition

type FieldDefinition struct {
	ID                 string        `toml:"id"`
	Name               string        `toml:"name"`
	Type               string        `toml:"type"`
	Required           bool          `toml:"required"`
	Description        string        `toml:"description"`
	Options            []FieldOption `toml:"options"`
	ReferenceWorkspace string        `toml:"reference_workspace"`
}

FieldDefinition represents a custom field definition

func (*FieldDefinition) Validate

func (f *FieldDefinition) Validate() error

Validate checks if the FieldDefinition is valid

type FieldOption

type FieldOption struct {
	ID          string         `toml:"id"`
	Name        string         `toml:"name"`
	Description string         `toml:"description"`
	Metadata    map[string]any `toml:"metadata"`
}

FieldOption represents an option for select/multi-select fields

func (*FieldOption) Validate

func (o *FieldOption) Validate(fieldID string) error

Validate checks if the FieldOption is valid

type GitHub

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

GitHub holds configuration for the GitHub App integration

func (*GitHub) Configure

func (g *GitHub) Configure() (*github.Client, error)

Configure creates a new GitHub Client from the configured flags. Returns nil if not all flags are configured (GitHub features will be disabled).

func (*GitHub) Flags

func (g *GitHub) Flags() []cli.Flag

Flags returns CLI flags for GitHub App configuration

func (*GitHub) IsConfigured

func (g *GitHub) IsConfigured() bool

IsConfigured returns true if all required GitHub App flags are set

func (*GitHub) LogAttrs

func (g *GitHub) LogAttrs() []slog.Attr

LogAttrs returns log attributes for the GitHub configuration (secrets hidden)

type GlobalConfig

type GlobalConfig struct {
	// Workspace captures a stray [workspace] section so the loader can reject
	// it. Workspace definitions belong under --config, never here. It is a raw
	// map (not the real WorkspaceBaseConfig) because its only use is presence
	// detection; an empty [workspace] table still unmarshals to a non-nil map.
	Workspace       map[string]any          `toml:"workspace"`
	WorkspaceGroups []WorkspaceGroupSection `toml:"workspace_group"`
	Export          *ExportSection          `toml:"export"`
	Agent           *AgentSection           `toml:"agent"`
	LLMModels       []LLMModelSection       `toml:"llm_model"`
}

GlobalConfig represents a deployment-wide configuration file supplied via --global-config. It is distinct from the per-workspace files under --config (which stay "1 file = 1 workspace"): a global config file carries settings that span workspaces. Today it holds workspace group definitions only; new deployment-wide sections can be added here later without a new flag.

type HomeMessageLLM

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

HomeMessageLLM is a dedicated, optional LLM configuration for the home dashboard's greeting message. It mirrors config.LLM's provider dispatch but with its own flags so the greeting can target a cheaper/faster model than the main chat LLM. When left unconfigured (IsEnabled() == false), the caller falls back to the shared chat LLM client.

func (*HomeMessageLLM) Flags

func (x *HomeMessageLLM) Flags() []cli.Flag

Flags returns CLI flags for the home-message LLM configuration.

func (*HomeMessageLLM) IsEnabled

func (x *HomeMessageLLM) IsEnabled() bool

IsEnabled reports whether a dedicated home-message LLM provider is configured. When false, the caller uses the shared chat LLM client instead.

func (*HomeMessageLLM) LogAttrs

func (x *HomeMessageLLM) LogAttrs() []slog.Attr

LogAttrs returns log attributes for the home-message LLM configuration. Secrets are never included.

func (*HomeMessageLLM) NewClient

func (x *HomeMessageLLM) NewClient(ctx context.Context) (gollem.LLMClient, error)

NewClient builds a gollem.LLMClient for the configured provider. It must only be called when IsEnabled() is true.

type Jira

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

Jira holds configuration for the Jira Cloud read-only integration.

func (*Jira) Configure

func (j *Jira) Configure(ctx context.Context) ([]gollem.Tool, error)

Configure builds the Jira agent tools from the configured flags. Returns nil, nil if none of the three flags are set (Jira features will be disabled). Returns an error if only some are set: a partial configuration is a setup mistake, not an intentional opt-out, and silently disabling the tools would hide it from the operator.

func (*Jira) Flags

func (j *Jira) Flags() []cli.Flag

Flags returns CLI flags for Jira configuration.

func (*Jira) IsConfigured

func (j *Jira) IsConfigured() bool

IsConfigured returns true if all required Jira flags are set.

func (*Jira) LogAttrs

func (j *Jira) LogAttrs() []slog.Attr

LogAttrs returns log attributes for the Jira configuration (the API token is deliberately excluded).

type JobConcurrency added in v0.3.0

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

JobConcurrency holds the CLI flag bounding how many scheduled Agent Job runs execute at the same time across every instance of the deployment. Shared by `serve` and `tick` because both dispatch Job runs.

func (*JobConcurrency) Flags added in v0.3.0

func (j *JobConcurrency) Flags() []cli.Flag

Flags returns the CLI flags for the Job concurrency limit.

func (*JobConcurrency) Limit added in v0.3.0

func (j *JobConcurrency) Limit() int

Limit returns the configured limit. 0 means no limit.

func (*JobConcurrency) LogAttrs added in v0.3.0

func (j *JobConcurrency) LogAttrs() []slog.Attr

LogAttrs returns log attributes describing the configuration.

func (*JobConcurrency) Validate added in v0.3.0

func (j *JobConcurrency) Validate() error

Validate rejects a negative limit. Called at startup so a typo fails fast instead of silently behaving like "no limit".

type JobEventsSection

type JobEventsSection struct {
	Case      *CaseEventSection      `toml:"case"`
	Scheduled *ScheduledEventSection `toml:"scheduled"`
}

JobEventsSection mirrors the `events.<domain> = { ... }` map. At least one sub-domain pointer must be non-nil; both may be set simultaneously.

type JobSection

type JobSection struct {
	ID          string `toml:"id"`
	Name        string `toml:"name"`
	Description string `toml:"description"`
	// Prompt is the inline prompt template. Exactly one of Prompt or
	// PromptFile must be set; supplying both, or neither, fails at config
	// load time.
	Prompt string `toml:"prompt"`
	// PromptFile points to a file holding the prompt template, resolved
	// relative to the config file's directory. It exists so long prompts can
	// live outside the TOML instead of being inlined. The file contents
	// replace Prompt once read (see resolvePrompt); the runtime layer only
	// ever sees the resolved model.Job.Prompt.
	PromptFile string `toml:"prompt_file"`
	Disabled   bool   `toml:"disabled"`
	// Quiet, when true, suppresses the operational Slack notifications a
	// Job run normally emits (the "starting..." marker, per-run session-log
	// thread, and completion/failure markers). Defaults to false.
	Quiet bool `toml:"quiet"`
	// Strategy selects the execution runtime for this Job. Empty falls
	// back to "simple" (the v1 SingleLoopJobExecutor); set to "planexec"
	// to drive the Job through the plan-and-execute runtime shared with
	// proposal. Unknown values fail loud at config load time.
	Strategy string `toml:"strategy"`
	// Reflection enables the post-execution reflection pass that curates
	// workspace Knowledge from a successful run's conversation history.
	// Defaults to false. Skipped for private cases and failed runs.
	Reflection bool `toml:"reflection"`
	// Interactive enables mid-run user interaction (planexec Question →
	// Slack form → resume). Defaults to false. Requires strategy="planexec";
	// the combination with simple is rejected at config load time by
	// model.Job.Validate.
	Interactive bool `toml:"interactive"`
	// LLMModel names which model this Job generates through: the reference name
	// of an [[llm_model]] entry in the global config (its alias, or its model
	// name when it declares no alias). Empty uses the deployment's default
	// model. Only the NAME's shape is checked here — whether it is defined
	// lives in another document, and is checked by ValidateJobModels.
	LLMModel string `toml:"llm_model"`
	// BudgetUSD is the greatest amount in USD one run of this Job may spend,
	// sub-agents included. Zero (the default) uses the deployment's default
	// budget.
	BudgetUSD float64          `toml:"budget_usd"`
	Events    JobEventsSection `toml:"events"`
}

JobSection is the TOML shape of a [[job]] entry. All event-shape validation runs at config load time: the runtime layer (pkg/usecase/job) trusts that every Job it receives has already been vetted.

func (*JobSection) Validate

func (s *JobSection) Validate(baseDir string) (*model.Job, error)

Validate parses and validates a single JobSection, returning a fully resolved model.Job on success. baseDir is the directory of the config file, used to resolve a relative prompt_file path. Returns an error wrapped with the job index so the caller can include it in its error message.

type LLM

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

LLM holds the CLI configuration for the agent's LLM access: which defined model is the default, and the credentials each provider needs.

It deliberately does NOT name a provider. Which provider serves a model — and what that model costs — is declared once per model in the global config's [[llm_model]] sections; naming it here as well would put the same fact in two places and make disagreement between them possible. What stays here is the credentials, because a secret does not belong in a configuration document.

func (*LLM) Flags

func (x *LLM) Flags() []cli.Flag

Flags returns CLI flags for LLM configuration.

func (*LLM) IsEnabled

func (x *LLM) IsEnabled() bool

IsEnabled reports whether a default model has been named. It is what decides whether the AI features are wired at all, the role --llm-provider used to play.

func (*LLM) LogAttrs

func (x *LLM) LogAttrs() []slog.Attr

LogAttrs returns log attributes for the LLM configuration. Secrets are never included. The resolved provider and model are logged by the caller that resolves them, since this struct names only the reference.

func (*LLM) ModelRef added in v0.3.0

func (x *LLM) ModelRef() string

ModelRef returns the reference name of the default model.

func (*LLM) NewClientFor added in v0.3.0

func (x *LLM) NewClientFor(ctx context.Context, def agentkernel.ModelDef) (gollem.LLMClient, error)

NewClientFor builds the gollem client that serves one defined model.

The credential rules are the provider's, not the model's: a claude model is reached either through Anthropic directly (an API key) or through Vertex AI (a GCP project), and naming both is a configuration mistake rather than a choice this code may make on the operator's behalf.

type LLMModelSection added in v0.3.0

type LLMModelSection struct {
	// Alias is the name Jobs and --llm-model refer to this entry by. Optional:
	// without it the reference name is Model.
	Alias string `toml:"alias"`
	// Provider is which client serves it: openai, claude or gemini.
	Provider string `toml:"provider"`
	// Model is the model name handed to that provider.
	Model string `toml:"model"`
	// InputUSDPerMTok and OutputUSDPerMTok are required and must be positive: a
	// model priced at nothing has an unbounded budget.
	InputUSDPerMTok  float64 `toml:"input_usd_per_mtok"`
	OutputUSDPerMTok float64 `toml:"output_usd_per_mtok"`
	// CacheReadUSDPerMTok and CacheWriteUSDPerMTok are optional (0 when the
	// provider bills no per-token cache read or write).
	CacheReadUSDPerMTok  float64 `toml:"cache_read_usd_per_mtok"`
	CacheWriteUSDPerMTok float64 `toml:"cache_write_usd_per_mtok"`
}

LLMModelSection is one [[llm_model]] entry: a model this deployment may use, and what it costs.

Prices are written in dollars per 1M tokens — the unit every provider publishes — and converted once, here. Writing them per token would mean ten-digit figures nobody can check against a price page.

func (*LLMModelSection) Validate added in v0.3.0

func (s *LLMModelSection) Validate() (agentkernel.ModelDef, error)

Validate checks one entry and returns its resolved form.

type Labels

type Labels struct {
	Case string `toml:"case"`
}

Labels represents entity display labels

type Logger

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

func (*Logger) Configure

func (x *Logger) Configure() (func(), error)

Configure sets up logger and returns closer function and error. You can call closer even if error is not nil.

func (*Logger) Flags

func (x *Logger) Flags() []cli.Flag

func (Logger) LogValue

func (x Logger) LogValue() slog.Value

type MCP

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

MCP holds the configuration for the MCP (Model Context Protocol) server endpoint and its Rego-based authorization. The MCP endpoint is only exposed when enabled, and only when at least one policy path is supplied — we never serve MCP without an authorization policy.

func (*MCP) Configure

func (m *MCP) Configure(c *cli.Command) (interfaces.PolicyClient, map[string]string, error)

Configure builds the PolicyClient and the env snapshot when MCP is enabled. It reads the slice flags from c (StringSliceFlag has no Destination).

When MCP is disabled it returns (nil, nil, nil). When MCP is enabled without any policy path it returns an error: exposing the MCP endpoint without an authorization policy would be an unauthenticated data leak, so we refuse to start rather than fall back to an open endpoint.

func (*MCP) Flags

func (m *MCP) Flags() []cli.Flag

Flags returns CLI flags for the MCP server and its policy source.

func (*MCP) IsEnabled

func (m *MCP) IsEnabled() bool

IsEnabled reports whether the MCP endpoint should be wired.

func (*MCP) LogAttrs

func (m *MCP) LogAttrs() []slog.Attr

LogAttrs returns log attributes describing the MCP configuration. Only the env variable names are logged, never their values.

type MemoSection

type MemoSection struct {
	// Description is the workspace's "strong definition" of the memo, injected
	// into the agent system prompt and shown in the WebUI.
	Description string `toml:"description"`
	// Fields are the memo custom field definitions ([[memo.fields]]), reusing
	// the same FieldDefinition schema as Case fields.
	Fields []FieldDefinition `toml:"fields"`
}

MemoSection represents the [memo] section in a TOML config. When omitted (nil) or with no fields, the workspace does not enable the memo feature.

type Repository

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

Repository holds CLI flags for repository backend configuration

func (*Repository) Backend

func (r *Repository) Backend() string

Backend returns the configured backend type

func (*Repository) Configure

func (r *Repository) Configure(ctx context.Context) (interfaces.Repository, error)

Configure initializes and returns a repository based on the configured backend. The caller is responsible for calling Close() on the returned repository.

func (*Repository) ConfigureAgentProcess added in v0.3.0

func (r *Repository) ConfigureAgentProcess(ctx context.Context) (agentkit.Repository, func(), error)

ConfigureAgentProcess builds the agentkit Process store on the same backend as the application repository. The returned cleanup closes the store's own Firestore client and must be called on shutdown.

It is a separate client from Configure's because the two implement different contracts and are consumed by different layers; sharing one would put the application repository's connection lifetime under the kernel's control.

func (*Repository) DatabaseID

func (r *Repository) DatabaseID() string

DatabaseID returns the Firestore database ID

func (*Repository) Flags

func (r *Repository) Flags() []cli.Flag

Flags returns CLI flags for repository configuration

func (*Repository) LogAttrs

func (r *Repository) LogAttrs() []slog.Attr

LogAttrs returns log attributes for the repository configuration

func (*Repository) ProjectID

func (r *Repository) ProjectID() string

ProjectID returns the Firestore project ID

type ScheduledEventSection

type ScheduledEventSection struct {
	Every string `toml:"every"`
	Cron  string `toml:"cron"`
}

ScheduledEventSection is the filter for `events.scheduled`. Exactly one of Every / Cron is required.

type Sentry

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

Sentry binds the HECATONCHEIRES_SENTRY_* CLI flags / env vars and drives the Sentry SDK lifecycle through errutil. An empty DSN keeps Sentry disabled and the rest of the values are ignored.

func (*Sentry) Configure

func (x *Sentry) Configure(ctx context.Context)

Configure initializes the Sentry SDK from the bound flags. When the DSN is empty Sentry stays disabled. SDK-level init errors are reported via errutil.Handle but never fail startup — losing Sentry must not block the service from coming up.

func (*Sentry) Flags

func (x *Sentry) Flags() []cli.Flag

Flags returns CLI flags for Sentry configuration.

func (Sentry) LogValue

func (x Sentry) LogValue() slog.Value

LogValue masks the DSN so it never lands in operational logs while still surfacing the rest of the Sentry configuration for diagnostics.

type Slack

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

func (*Slack) AuthTeamID

func (x *Slack) AuthTeamID() string

AuthTeamID returns the team_id from auth.test response

func (*Slack) BotToken

func (x *Slack) BotToken() string

BotToken returns the Slack bot token

func (*Slack) Configure

func (x *Slack) Configure(ctx context.Context, repo interfaces.Repository, baseURL string) (usecase.AuthUseCaseInterface, error)

Configure creates an AuthUseCase if Slack is configured, otherwise returns NoAuthnUseCase

func (*Slack) DetectOrgLevel

func (x *Slack) DetectOrgLevel(ctx context.Context) error

DetectOrgLevel calls auth.test and auth.teams.list to determine if the bot token has access to multiple workspaces (multi-team / org-level behavior). It stores the result (isOrgLevel, authTeamID, enterpriseID) for later validation. If botToken is empty, this is a no-op (Slack features disabled).

func (*Slack) EnterpriseID

func (x *Slack) EnterpriseID() string

EnterpriseID returns the enterprise_id from auth.test response (empty for WS-level apps)

func (*Slack) Flags

func (x *Slack) Flags() []cli.Flag

Flags is the full Slack surface: the runtime flags below plus the ones only an HTTP process uses (the OAuth client pair and the signing secret that verifies inbound webhooks). A command that serves no endpoints registers RuntimeFlags instead, so its deployment is never asked for credentials it cannot use.

func (*Slack) GetSlackUserInfo

func (x *Slack) GetSlackUserInfo(ctx context.Context, userID string) (*SlackUserInfo, error)

GetSlackUserInfo retrieves user information from Slack API

func (*Slack) IsConfigured

func (x *Slack) IsConfigured() bool

IsConfigured checks if Slack configuration is complete

func (*Slack) IsNoAuthMode

func (x *Slack) IsNoAuthMode() bool

IsNoAuthMode returns true if no-auth mode is enabled

func (*Slack) IsOrgLevel

func (x *Slack) IsOrgLevel() bool

IsOrgLevel returns whether the Slack app is org-level installed

func (*Slack) IsWebhookConfigured

func (x *Slack) IsWebhookConfigured() bool

IsWebhookConfigured checks if Slack webhook is configured

func (*Slack) LogAttrs

func (x *Slack) LogAttrs() []slog.Attr

LogAttrs returns log attributes for the Slack configuration (secrets hidden)

func (Slack) LogValue

func (x Slack) LogValue() slog.Value

func (*Slack) NoAuthUID

func (x *Slack) NoAuthUID() string

NoAuthUID returns the no-auth user ID

func (*Slack) NotificationSlotDuration

func (x *Slack) NotificationSlotDuration() time.Duration

NotificationSlotDuration returns the configured aggregation window.

func (*Slack) RuntimeFlags added in v0.3.0

func (x *Slack) RuntimeFlags() []cli.Flag

RuntimeFlags is the subset a process needs to TALK to Slack: the two tokens the API clients are built from and the notification aggregation window. It carries nothing that authenticates an inbound request, because a command with no HTTP surface has no inbound request to authenticate.

func (*Slack) SetNoAuthUID

func (x *Slack) SetNoAuthUID(uid string)

SetNoAuthUID sets the no-auth user ID

func (*Slack) SigningSecret

func (x *Slack) SigningSecret() string

SigningSecret returns the Slack signing secret

func (*Slack) UserOAuthToken

func (x *Slack) UserOAuthToken() string

UserOAuthToken returns the Slack User OAuth Token for admin API operations

func (*Slack) ValidateWorkspaceTeamIDs

func (x *Slack) ValidateWorkspaceTeamIDs(configs []*WorkspaceConfig) error

ValidateWorkspaceTeamIDs validates slack.team_id settings in workspace configs based on whether the app is org-level or workspace-level.

  • Org-Level App: all workspaces must have slack.team_id set
  • WS-Level App: slack.team_id may be empty; if set, must match auth.test team_id

If botToken is empty (Slack disabled), validation is skipped.

type SlackInviteSection

type SlackInviteSection struct {
	Users  []string `toml:"users"`
	Groups []string `toml:"groups"`
}

SlackInviteSection represents the [slack.invite] section in a TOML config

type SlackSection

type SlackSection struct {
	ChannelPrefix   string             `toml:"channel_prefix"`
	TeamID          string             `toml:"team_id"`
	Invite          SlackInviteSection `toml:"invite"`
	WelcomeMessages []string           `toml:"welcome_messages"`
	// Mode selects the case-binding mode: "channel" (default) or "thread".
	Mode string `toml:"mode"`
	// Channel is the monitored Slack channel ID for thread mode (e.g. C0123...).
	Channel string `toml:"channel"`
	// AcceptBot, when true, makes bot-authored events (a channel-root post in
	// instant mode, or an @mention in mention mode) start a case in thread mode.
	// Default false: only human-authored events start a case.
	AcceptBot bool `toml:"accept_bot"`
	// Trigger selects what starts a case in thread mode: "instant" (default,
	// every channel-root post) or "mention" (only an @mention of the bot).
	// Ignored in channel mode.
	Trigger string `toml:"trigger"`
	// Reaction is the emoji name (with or without surrounding colons) that
	// triggers case creation when added to any visible message. Thread mode
	// only; empty disables the reaction trigger.
	Reaction string `toml:"reaction"`
	// WorkspaceChannel is the workspace-level shared channel ID where the
	// cross-case workspace agent runs (and future notifications flow). It
	// parallels Channel but is channel-mode only; empty disables the feature.
	WorkspaceChannel string `toml:"workspace_channel"`
	// WorkspaceAgent configures the cross-case agent ([slack.workspace_agent]).
	// nil when the subsection is omitted. Valid in both modes: in channel mode
	// the agent runs in WorkspaceChannel (which must then be set), in thread
	// mode it runs on a channel-root mention in the monitored Channel.
	WorkspaceAgent *WorkspaceAgentSection `toml:"workspace_agent"`
}

SlackSection represents the slack section in a TOML config

type SlackTool added in v0.3.0

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

SlackTool holds the size bounds applied to the Slack read tools' results. It is separate from Slack because it configures no credential and reaches no API: it bounds what a tool result may inject into the model context, the way WebFetch does for a fetched page.

func (*SlackTool) Flags added in v0.3.0

func (s *SlackTool) Flags() []cli.Flag

Flags returns CLI flags for the Slack agent tools.

One pair covers every Slack read tool rather than one pair per tool, so an operator sets a single budget for what a Slack read may inject and a tool added later is bounded without a new flag.

func (*SlackTool) Limits added in v0.3.0

func (s *SlackTool) Limits() slacktool.Limits

Limits returns the bounds the Slack read tools apply to their results.

func (*SlackTool) LogAttrs added in v0.3.0

func (s *SlackTool) LogAttrs() []slog.Attr

LogAttrs returns log attributes for the Slack tool configuration.

func (*SlackTool) Validate added in v0.3.0

func (s *SlackTool) Validate() error

Validate rejects a negative bound. Called at startup so a typo fails fast instead of silently behaving like "no limit": the tools read any non-positive value as "this bound is off", so `-1` would start a deployment with Slack reads unbounded and nothing but the startup log to show for it.

type SlackUserInfo

type SlackUserInfo struct {
	ID    string
	Email string
	Name  string
}

SlackUserInfo holds user information retrieved from Slack API

type Storage

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

Storage holds CLI flags for the Cloud Storage backend used by the agent session archive (gollem History + Trace persistence).

func (*Storage) Bucket

func (s *Storage) Bucket() string

Bucket returns the configured bucket name.

func (*Storage) Configure

func (s *Storage) Configure(ctx context.Context) (*Archive, error)

Configure builds the Cloud Storage-backed archive. An error is returned when the bucket flag is empty.

func (*Storage) Flags

func (s *Storage) Flags() []cli.Flag

Flags returns the CLI flags for Cloud Storage configuration.

func (*Storage) LogAttrs

func (s *Storage) LogAttrs() []slog.Attr

LogAttrs returns log attributes describing the configuration.

func (*Storage) Prefix

func (s *Storage) Prefix() string

Prefix returns the configured object key prefix.

type WebFetch

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

WebFetch holds configuration for the agent webfetch tool. The shared LLM client (used for injection screening + Markdown formatting) is NOT held here: it lives in the usecase layer and is injected when the client is built.

func (*WebFetch) Flags

func (w *WebFetch) Flags() []cli.Flag

Flags returns CLI flags for the webfetch tool.

func (*WebFetch) IsEnabled

func (w *WebFetch) IsEnabled() bool

IsEnabled reports whether the webfetch tool should be wired.

func (*WebFetch) LogAttrs

func (w *WebFetch) LogAttrs() []slog.Attr

LogAttrs returns log attributes for the webfetch configuration.

func (*WebFetch) Settings

func (w *WebFetch) Settings() webfetch.ClientConfig

Settings returns the HTTP-side client config. ClientConfig.LLM is left nil: the usecase layer injects the shared LLM client before building the client.

type WorkspaceAgentSection

type WorkspaceAgentSection struct {
	Prompt     string `toml:"prompt"`
	PromptFile string `toml:"prompt_file"`
}

WorkspaceAgentSection represents the [slack.workspace_agent] subsection: the custom prompt for the cross-case agent that runs in the workspace channel.

type WorkspaceBaseConfig

type WorkspaceBaseConfig struct {
	ID          string `toml:"id"`
	Name        string `toml:"name"`
	Description string `toml:"description"` // Human-readable description used to disambiguate workspaces (especially for AI-side workspace estimation)
	// Emoji is an optional display glyph rendered in the workspace badge.
	// Mutually exclusive with Color. Empty when unset.
	Emoji string `toml:"emoji"`
	// Color is an optional #RRGGBB hex used as the workspace badge background.
	// Mutually exclusive with Emoji. Empty when unset.
	Color string `toml:"color"`
}

WorkspaceBaseConfig represents the [workspace] section in a TOML config

func (*WorkspaceBaseConfig) Validate

func (w *WorkspaceBaseConfig) Validate() error

Validate checks the optional emoji/color fields of the [workspace] section. emoji and color are mutually exclusive; color must be a #RRGGBB hex code; emoji must not exceed maxWorkspaceEmojiRunes runes.

type WorkspaceConfig

type WorkspaceConfig struct {
	ID                   string
	Name                 string
	Description          string
	Emoji                string
	Color                string
	SlackChannelPrefix   string
	SlackTeamID          string
	SlackInviteUsers     []string
	SlackInviteGroups    []string
	SlackWelcomeMessages []string
	FieldSchema          *domainConfig.FieldSchema
	MemoConfig           *domainConfig.MemoConfig
	ActionStatusSet      *model.ActionStatusSet
	CompilePrompt        string
	AssistPrompt         string
	AssistLanguage       string
	// CaseCreatePrompt is the workspace-specific additional prompt for the
	// thread-mode case initialization agent, from [case.prompts].create.
	CaseCreatePrompt    string
	Jobs                []*model.Job
	CaseMode            model.CaseMode
	CaseTrigger         model.CaseTrigger
	SlackMonitorChannel string
	AcceptBot           bool
	CaseStatusSet       *model.ActionStatusSet
	// ReactionEmoji is the normalized (colon-stripped) reaction trigger emoji,
	// empty when disabled.
	ReactionEmoji string
	// WorkspaceChannelID is the workspace-level shared channel ID (channel mode
	// only), empty when unset.
	WorkspaceChannelID string
	// WorkspaceAgentPrompt is the resolved custom prompt for the workspace agent
	// (from [slack.workspace_agent] prompt/prompt_file), empty when unset.
	WorkspaceAgentPrompt string
}

WorkspaceConfig represents a fully resolved workspace configuration

func LoadWorkspaceConfigs

func LoadWorkspaceConfigs(paths []string) ([]*WorkspaceConfig, error)

LoadWorkspaceConfigs loads workspace configurations from multiple paths. Each path can be a file or directory. Directories are walked recursively for .toml files.

func ParseWorkspaceConfigs added in v0.3.0

func ParseWorkspaceConfigs(sources []WorkspaceConfigSource) ([]*WorkspaceConfig, error)

ParseWorkspaceConfigs parses and validates in-memory workspace configuration documents. It carries the checks that can only run once every workspace is known: duplicate workspace ids, duplicate reaction emojis, case_ref fields naming an unknown reference workspace, and channel routing collisions.

type WorkspaceConfigSource added in v0.3.0

type WorkspaceConfigSource struct {
	// Name identifies the document in error messages and log fields: the file
	// path when the document was read from disk, the request part name when it
	// arrived over HTTP.
	Name string
	// Data is the raw TOML document.
	Data []byte
	// BaseDir is the directory a relative prompt_file is resolved against.
	// Leave it empty for a document that has no directory of its own (one
	// submitted over HTTP): the parse then reads no files at all and the
	// prompt_file contents stay unresolved, which is the structural-validation
	// mode JobSection.Validate and WorkspaceAgentSection.resolvePrompt already
	// implement. Resolving a submitted document's prompt_file against the
	// server's filesystem would turn config submission into an arbitrary file
	// read.
	BaseDir string
}

WorkspaceConfigSource is one workspace configuration document handed to ParseWorkspaceConfigs.

type WorkspaceGroupSection

type WorkspaceGroupSection struct {
	ID          string   `toml:"id"`
	Name        string   `toml:"name"`
	Description string   `toml:"description"`
	Members     []string `toml:"members"`
}

WorkspaceGroupSection represents a single [[workspace_group]] table.

func (*WorkspaceGroupSection) Validate

func (s *WorkspaceGroupSection) Validate() error

Validate checks one group section in isolation: id presence and format, and member uniqueness within this group. Cross-file id uniqueness and member existence are enforced by the loader / ConfigureGroups once the full group and workspace sets are known.

Jump to

Keyboard shortcuts

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