Documentation
¶
Index ¶
- Constants
- Variables
- func LoadFieldSchema(path string) (*domainConfig.FieldSchema, error)
- func LoadWorkspaceGroups(paths []string) ([]*model.WorkspaceGroup, error)
- type ActionSection
- type ActionStatusConfigRow
- type AppConfig
- func (a *AppConfig) Configure(c *cli.Command) ([]*WorkspaceConfig, *model.WorkspaceRegistry, error)
- func (a *AppConfig) ConfigureExport(c *cli.Command, ws *model.WorkspaceRegistry) (*ExportSection, error)
- func (a *AppConfig) ConfigureGroups(c *cli.Command, ws *model.WorkspaceRegistry) (*model.WorkspaceGroupRegistry, error)
- func (a *AppConfig) Flags() []cli.Flag
- func (a *AppConfig) ToDomainFieldSchema() *domainConfig.FieldSchema
- func (a *AppConfig) ToDomainMemoConfig() *domainConfig.MemoConfig
- func (a *AppConfig) Validate() error
- type AssistSection
- type CaseEventSection
- type CasePromptsSection
- type CaseSection
- type CompileSection
- type Embedding
- type ExportBigQuerySection
- type ExportSection
- type ExportWorkspaceMapping
- type FieldDefinition
- type FieldOption
- type GitHub
- type GlobalConfig
- type HomeMessageLLM
- type Jira
- type JobEventsSection
- type JobSection
- type LLM
- type Labels
- type Logger
- type MCP
- type MemoSection
- type Repository
- type ScheduledEventSection
- type Sentry
- type Slack
- func (x *Slack) AuthTeamID() string
- func (x *Slack) BotToken() string
- func (x *Slack) Configure(ctx context.Context, repo interfaces.Repository, baseURL string) (usecase.AuthUseCaseInterface, error)
- func (x *Slack) DetectOrgLevel(ctx context.Context) error
- func (x *Slack) EnterpriseID() string
- func (x *Slack) Flags() []cli.Flag
- func (x *Slack) GetSlackUserInfo(ctx context.Context, userID string) (*SlackUserInfo, error)
- func (x *Slack) IsConfigured() bool
- func (x *Slack) IsNoAuthMode() bool
- func (x *Slack) IsOrgLevel() bool
- func (x *Slack) IsWebhookConfigured() bool
- func (x *Slack) LogAttrs() []slog.Attr
- func (x Slack) LogValue() slog.Value
- func (x *Slack) NoAuthUID() string
- func (x *Slack) NotificationSlotDuration() time.Duration
- func (x *Slack) SetNoAuthUID(uid string)
- func (x *Slack) SigningSecret() string
- func (x *Slack) UserOAuthToken() string
- func (x *Slack) ValidateWorkspaceTeamIDs(configs []*WorkspaceConfig) error
- type SlackInviteSection
- type SlackSection
- type SlackUserInfo
- type Storage
- type WebFetch
- type WorkspaceAgentSection
- type WorkspaceBaseConfig
- type WorkspaceConfig
- type WorkspaceGroupSection
Constants ¶
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" )
Context keys for error values
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 ¶
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") )
Sentinel errors for configuration validation
Functions ¶
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 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.
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 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 ¶
func (a *AppConfig) Configure(c *cli.Command) ([]*WorkspaceConfig, *model.WorkspaceRegistry, error)
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) 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 ¶
func (a *AppConfig) ConfigureGroups(c *cli.Command, ws *model.WorkspaceRegistry) (*model.WorkspaceGroupRegistry, error)
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) 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.
type AssistSection ¶
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) IsEnabled ¶
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 ¶
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 ¶
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) IsConfigured ¶
IsConfigured returns true if all required GitHub App flags are set
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"`
}
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.
type Jira ¶
type Jira struct {
// contains filtered or unexported fields
}
Jira holds configuration for the Jira Cloud read-only integration.
func (*Jira) Configure ¶
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) IsConfigured ¶
IsConfigured returns true if all required Jira flags are set.
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"`
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 CLI configuration for LLM clients backed by gollem. It supports OpenAI, Anthropic Claude (direct API or Vertex AI), and Google Gemini.
type Labels ¶
type Labels struct {
Case string `toml:"case"`
}
Labels represents entity display labels
type Logger ¶
type Logger struct {
// contains filtered or unexported fields
}
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.
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) 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 ¶
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 ¶
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.
type Slack ¶
type Slack struct {
// contains filtered or unexported fields
}
func (*Slack) AuthTeamID ¶
AuthTeamID returns the team_id from auth.test response
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 ¶
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 ¶
EnterpriseID returns the enterprise_id from auth.test response (empty for WS-level apps)
func (*Slack) GetSlackUserInfo ¶
GetSlackUserInfo retrieves user information from Slack API
func (*Slack) IsConfigured ¶
IsConfigured checks if Slack configuration is complete
func (*Slack) IsNoAuthMode ¶
IsNoAuthMode returns true if no-auth mode is enabled
func (*Slack) IsOrgLevel ¶
IsOrgLevel returns whether the Slack app is org-level installed
func (*Slack) IsWebhookConfigured ¶
IsWebhookConfigured checks if Slack webhook is configured
func (*Slack) LogAttrs ¶
LogAttrs returns log attributes for the Slack configuration (secrets hidden)
func (*Slack) NotificationSlotDuration ¶
NotificationSlotDuration returns the configured aggregation window.
func (*Slack) SetNoAuthUID ¶
SetNoAuthUID sets the no-auth user ID
func (*Slack) SigningSecret ¶
SigningSecret returns the Slack signing secret
func (*Slack) UserOAuthToken ¶
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 ¶
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 SlackUserInfo ¶
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) Configure ¶
func (s *Storage) Configure(ctx context.Context) (gollem.HistoryRepository, trace.Repository, func(), error)
Configure builds the gollem HistoryRepository and trace.Repository backed by Cloud Storage. The returned cleanup function closes the underlying storage client and must be called on shutdown. An error is returned when the bucket flag is empty.
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) 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.
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.