Documentation
¶
Index ¶
- Constants
- Variables
- func NewActionStepToolAdapter(uc *ActionStepUseCase) core.ActionStepMutator
- func NewActionToolAdapter(uc *ActionUseCase) core.ActionMutator
- func NewCaseMultiActionAdapter(action *ActionUseCase, step *ActionStepUseCase) casemulti.ActionUsecase
- func NewCaseMultiCaseAdapter(uc *CaseUseCase) casemulti.CaseUsecase
- func NewCaseToolAdapter(uc *CaseUseCase) casewriter.CaseMutator
- func NewKnowledgeToolAccessor(uc *KnowledgeUseCase, tagUC *TagUseCase) knowledgetool.KnowledgeAccessor
- func NewKnowledgeToolMutator(uc *KnowledgeUseCase, tagUC *TagUseCase) knowledgetool.KnowledgeMutator
- func NewMemoToolAdapter(uc *MemoUseCase) memotool.MemoMutator
- func ParseAgentActionValue(value string) (action string, data string, err error)
- func ParseSlackAssigneeBlockID(blockID string) (workspaceID string, actionID int64, err error)
- func ParseSlackStatusSelectValue(value string) (workspaceID string, actionID int64, status types.ActionStatus, err error)
- func SlackActionAssigneeBlockID(workspaceID string, actionID int64) string
- type ActionStepUseCase
- func (uc *ActionStepUseCase) Add(ctx context.Context, in AddActionStepInput) (*model.ActionStep, error)
- func (uc *ActionStepUseCase) Delete(ctx context.Context, in DeleteActionStepInput) error
- func (uc *ActionStepUseCase) List(ctx context.Context, workspaceID string, actionID int64) ([]*model.ActionStep, error)
- func (uc *ActionStepUseCase) Progress(ctx context.Context, workspaceID string, actionID int64) (int, int, error)
- func (uc *ActionStepUseCase) Rename(ctx context.Context, in RenameActionStepInput) (*model.ActionStep, error)
- func (uc *ActionStepUseCase) SetDone(ctx context.Context, in SetActionStepDoneInput) (*model.ActionStep, error)
- type ActionUseCase
- func (uc *ActionUseCase) ArchiveAction(ctx context.Context, workspaceID string, id int64, actor ActorRef) (*model.Action, error)
- func (uc *ActionUseCase) BulkArchiveActions(ctx context.Context, workspaceID string, ids []int64, actor ActorRef) ([]*model.Action, error)
- func (uc *ActionUseCase) BulkArchiveActionsAsync(ctx context.Context, workspaceID string, ids []int64, actor ActorRef)
- func (uc *ActionUseCase) CreateAction(ctx context.Context, workspaceID string, caseID int64, ...) (*model.Action, error)
- func (uc *ActionUseCase) GetAction(ctx context.Context, workspaceID string, id int64, ...) (*model.Action, error)
- func (uc *ActionUseCase) GetActions(ctx context.Context, workspaceID string, ids []int64, ...) ([]*model.Action, error)
- func (uc *ActionUseCase) GetActionsByCase(ctx context.Context, workspaceID string, caseID int64, ...) ([]*model.Action, error)
- func (uc *ActionUseCase) ListActions(ctx context.Context, workspaceID string, opts interfaces.ActionListOptions) ([]*model.Action, error)
- func (uc *ActionUseCase) ListOpenCaseActions(ctx context.Context, workspaceID string) ([]*model.Action, error)
- func (uc *ActionUseCase) PostSlackMessageToAction(ctx context.Context, workspaceID string, actionID int64) (*model.Action, error)
- func (uc *ActionUseCase) UnarchiveAction(ctx context.Context, workspaceID string, id int64, actor ActorRef) (*model.Action, error)
- func (uc *ActionUseCase) UpdateAction(ctx context.Context, workspaceID string, in UpdateActionInput) (*model.Action, error)
- type ActorKind
- type ActorRef
- type AddActionStepInput
- type AgentDeps
- type AgentUseCase
- func (uc *AgentUseCase) HandleAgentMention(ctx context.Context, msg *slackmodel.Message) error
- func (uc *AgentUseCase) HandleSessionInfoRequest(ctx context.Context, triggerID, sessionID string) error
- func (uc *AgentUseCase) HandleThreadCaseCreation(ctx context.Context, msg *slackmodel.Message, entry *model.WorkspaceEntry) error
- func (uc *AgentUseCase) HandleThreadCaseMention(ctx context.Context, msg *slackmodel.Message, entry *model.WorkspaceEntry, ...) error
- func (uc *AgentUseCase) HandleThreadCaseMentionCreation(ctx context.Context, msg *slackmodel.Message, entry *model.WorkspaceEntry) error
- func (uc *AgentUseCase) HandleThreadCaseQuestionSubmit(ctx context.Context, callback *goslack.InteractionCallback, ...) error
- func (uc *AgentUseCase) HandleWorkspaceAgentMention(ctx context.Context, msg *slackmodel.Message, entry *model.WorkspaceEntry) error
- func (uc *AgentUseCase) ResumeThreadCaseCreation(ctx context.Context, msg *slackmodel.Message, entry *model.WorkspaceEntry) error
- type AssistDeps
- type AssistOption
- type AssistUseCase
- type AuthOption
- type AuthUseCase
- func (uc *AuthUseCase) GetAuthURL(state string) string
- func (uc *AuthUseCase) HandleCallback(ctx context.Context, code string) (*auth.Token, error)
- func (uc *AuthUseCase) IsNoAuthn() bool
- func (uc *AuthUseCase) Logout(ctx context.Context, tokenID auth.TokenID) error
- func (uc *AuthUseCase) ValidateToken(ctx context.Context, tokenID auth.TokenID, tokenSecret auth.TokenSecret) (*auth.Token, error)
- type AuthUseCaseInterface
- type CaseEventPublisher
- type CaseUpdate
- type CaseUseCase
- func (uc *CaseUseCase) AssignCase(ctx context.Context, workspaceID string, id int64, userIDs []string) (*model.Case, error)
- func (uc *CaseUseCase) CaseURL(workspaceID string, caseID int64) string
- func (uc *CaseUseCase) CloseCase(ctx context.Context, workspaceID string, id int64) (*model.Case, error)
- func (uc *CaseUseCase) CreateCase(ctx context.Context, workspaceID string, title, description string, ...) (*model.Case, error)
- func (uc *CaseUseCase) CreateDraft(ctx context.Context, workspaceID string, title, description string, ...) (*model.Case, error)
- func (uc *CaseUseCase) DeleteCase(ctx context.Context, workspaceID string, id int64) error
- func (uc *CaseUseCase) DiscardDraft(ctx context.Context, workspaceID string, id int64) error
- func (uc *CaseUseCase) GetActionStatusSet(workspaceID string) *model.ActionStatusSet
- func (uc *CaseUseCase) GetCase(ctx context.Context, workspaceID string, id int64) (*model.Case, error)
- func (uc *CaseUseCase) GetCaseStatusSet(workspaceID string) *model.ActionStatusSet
- func (uc *CaseUseCase) GetCases(ctx context.Context, workspaceID string, ids []int64) ([]*model.Case, error)
- func (uc *CaseUseCase) GetDraft(ctx context.Context, workspaceID string, id int64) (*model.Case, error)
- func (uc *CaseUseCase) GetFieldConfiguration(workspaceID string) *config.FieldSchema
- func (uc *CaseUseCase) GetReferenceableCases(ctx context.Context, workspaceID string, ids []int64) ([]*model.Case, error)
- func (uc *CaseUseCase) ListCases(ctx context.Context, workspaceID string, status *types.CaseStatus) ([]*model.Case, error)
- func (uc *CaseUseCase) ListDrafts(ctx context.Context, workspaceID string) ([]*model.Case, error)
- func (uc *CaseUseCase) ListReferenceableCases(ctx context.Context, workspaceID, query string, limit int) ([]model.CaseRef, error)
- func (uc *CaseUseCase) MaterializeThreadCase(ctx context.Context, workspaceID string, id int64, title, description string, ...) (*model.Case, error)
- func (uc *CaseUseCase) ReferenceWorkspaceForField(workspaceID, fieldID string) (string, error)
- func (uc *CaseUseCase) RenderCaseFieldValues(ctx context.Context, workspaceID string, ...) (map[string]any, error)
- func (uc *CaseUseCase) ReopenCase(ctx context.Context, workspaceID string, id int64) (*model.Case, error)
- func (uc *CaseUseCase) ResolveCaseRefs(ctx context.Context, workspaceID string, ids []int64) ([]model.CaseRef, error)
- func (uc *CaseUseCase) SetEventPublisher(p CaseEventPublisher)
- func (uc *CaseUseCase) SubmitDraft(ctx context.Context, workspaceID string, id int64, patch *CaseUpdate) (*model.Case, error)
- func (uc *CaseUseCase) SyncCaseChannelUsers(ctx context.Context, workspaceID string, caseID int64) (*model.Case, error)
- func (uc *CaseUseCase) UnassignCase(ctx context.Context, workspaceID string, id int64, userIDs []string) (*model.Case, error)
- func (uc *CaseUseCase) UpdateAgentSettings(ctx context.Context, workspaceID string, caseID int64, additionalPrompt string, ...) (*model.Case, error)
- func (uc *CaseUseCase) UpdateCase(ctx context.Context, workspaceID string, id int64, patch CaseUpdate) (*model.Case, error)
- func (uc *CaseUseCase) UpdateCaseStatus(ctx context.Context, workspaceID string, id int64, boardStatus string) (*model.Case, error)
- type CreateGitHubSourceInput
- type CreateKnowledgeInput
- type CreateMemoInput
- type CreateNotionDBSourceInput
- type CreateNotionPageSourceInput
- type CreateSlackSourceInput
- type DashboardUseCase
- func (uc *DashboardUseCase) GenerateHomeMessage(ctx context.Context, clientTime time.Time, lang string) (string, error)
- func (uc *DashboardUseCase) GetFavoriteWorkspaces(ctx context.Context) ([]string, error)
- func (uc *DashboardUseCase) ListMyDueActions(ctx context.Context) ([]*model.MyDueAction, error)
- func (uc *DashboardUseCase) ListMyOpenCases(ctx context.Context) ([]*model.MyOpenCase, error)
- func (uc *DashboardUseCase) SetFavoriteWorkspaces(ctx context.Context, workspaceIDs []string) ([]string, error)
- type DeleteActionStepInput
- type GitHubRepoValidationResult
- type ImportUseCase
- func (uc *ImportUseCase) Create(ctx context.Context, workspaceID, content, originalFileName string) (*model.ImportSession, error)
- func (uc *ImportUseCase) Execute(ctx context.Context, workspaceID string, id model.ImportSessionID) (*model.ImportSession, error)
- func (uc *ImportUseCase) Get(ctx context.Context, workspaceID string, id model.ImportSessionID) (*model.ImportSession, error)
- type JobRunLogPage
- type JobRunUseCase
- func (uc *JobRunUseCase) GetLog(ctx context.Context, workspaceID string, caseID int64, runID string) (*model.JobRunLog, error)
- func (uc *JobRunUseCase) ListCaseJobs(ctx context.Context, workspaceID string, caseID int64) ([]*model.Job, error)
- func (uc *JobRunUseCase) ListEvents(ctx context.Context, workspaceID string, caseID int64, runID string) ([]*model.JobRunEvent, error)
- func (uc *JobRunUseCase) ListLogsByCase(ctx context.Context, workspaceID string, caseID int64, page int, after *string) (*JobRunLogPage, error)
- func (uc *JobRunUseCase) ResolveJobName(ctx context.Context, workspaceID, jobID, eventType string) string
- type KnowledgeUseCase
- func (uc *KnowledgeUseCase) CreateKnowledge(ctx context.Context, workspaceID string, input CreateKnowledgeInput) (*model.Knowledge, error)
- func (uc *KnowledgeUseCase) DeleteKnowledge(ctx context.Context, workspaceID string, id model.KnowledgeID) error
- func (uc *KnowledgeUseCase) GetKnowledge(ctx context.Context, workspaceID string, id model.KnowledgeID) (*model.Knowledge, error)
- func (uc *KnowledgeUseCase) ListKnowledge(ctx context.Context, workspaceID string, opts interfaces.KnowledgeListOptions) ([]*model.Knowledge, error)
- func (uc *KnowledgeUseCase) SearchKnowledge(ctx context.Context, workspaceID string, input SearchKnowledgeInput) ([]*model.Knowledge, error)
- func (uc *KnowledgeUseCase) UpdateKnowledge(ctx context.Context, workspaceID string, input UpdateKnowledgeInput) (*model.Knowledge, error)
- type MemoConfiguration
- type MemoUseCase
- func (uc *MemoUseCase) ArchiveMemo(ctx context.Context, workspaceID string, caseID int64, id model.MemoID) (*model.Memo, error)
- func (uc *MemoUseCase) CreateMemo(ctx context.Context, workspaceID string, in CreateMemoInput) (*model.Memo, error)
- func (uc *MemoUseCase) GetMemo(ctx context.Context, workspaceID string, caseID int64, id model.MemoID) (*model.Memo, error)
- func (uc *MemoUseCase) ListMemosByCase(ctx context.Context, workspaceID string, caseID int64, ...) ([]*model.Memo, error)
- func (uc *MemoUseCase) MemoConfiguration(workspaceID string) (*MemoConfiguration, error)
- func (uc *MemoUseCase) UnarchiveMemo(ctx context.Context, workspaceID string, caseID int64, id model.MemoID) (*model.Memo, error)
- func (uc *MemoUseCase) UpdateMemo(ctx context.Context, workspaceID string, in UpdateMemoInput) (*model.Memo, error)
- type MentionProposalUseCase
- func (uc *MentionProposalUseCase) HandleAppMention(ctx context.Context, ev *slackevents.AppMentionEvent) error
- func (uc *MentionProposalUseCase) HandleCancel(ctx context.Context, callback *goslack.InteractionCallback, ...) error
- func (uc *MentionProposalUseCase) HandleEdit(ctx context.Context, callback *goslack.InteractionCallback, ...) error
- func (uc *MentionProposalUseCase) HandleEditSubmit(ctx context.Context, caseUC *CaseUseCase, ...) error
- func (uc *MentionProposalUseCase) HandleQuestionSubmit(ctx context.Context, callback *goslack.InteractionCallback, ...) error
- func (uc *MentionProposalUseCase) HandleSelectWorkspace(ctx context.Context, callback *goslack.InteractionCallback, ...) error
- func (uc *MentionProposalUseCase) HandleSubmit(ctx context.Context, caseUC *CaseUseCase, ...) error
- func (uc *MentionProposalUseCase) HandleThreadReply(ctx context.Context, ev *slackevents.MessageEvent) error
- type NoAuthnUseCase
- func (uc *NoAuthnUseCase) GetAuthURL(state string) string
- func (uc *NoAuthnUseCase) HandleCallback(ctx context.Context, code string) (*auth.Token, error)
- func (uc *NoAuthnUseCase) IsNoAuthn() bool
- func (uc *NoAuthnUseCase) Logout(ctx context.Context, tokenID auth.TokenID) error
- func (uc *NoAuthnUseCase) ValidateToken(ctx context.Context, tokenID auth.TokenID, tokenSecret auth.TokenSecret) (*auth.Token, error)
- type NotionDBValidationResult
- type NotionPageValidationResult
- type OpenIDConfiguration
- type Option
- func WithAuth(auth AuthUseCaseInterface) Option
- func WithBaseURL(url string) Option
- func WithDashboardStaleThreshold(d time.Duration) Option
- func WithEmbedClient(client interfaces.EmbedClient) Option
- func WithGitHubService(c *github.Client) Option
- func WithHistoryRepository(repo gollem.HistoryRepository) Option
- func WithHomeMessageLLMClient(client gollem.LLMClient) Option
- func WithJiraTools(tools []gollem.Tool) Option
- func WithLLMClient(client gollem.LLMClient) Option
- func WithNotificationSlotDuration(d time.Duration) Option
- func WithNotion(svc notion.Service) Option
- func WithNotionToolClient(c notiontool.Client) Option
- func WithSlackAdminService(svc slack.AdminService) Option
- func WithSlackMessageRetriever(svc slacktool.MessageRetriever) Option
- func WithSlackSearchService(svc slacktool.SearchService) Option
- func WithSlackService(svc slack.Service) Option
- func WithTraceRepository(repo trace.Repository) Option
- func WithWebFetch(cfg webfetch.ClientConfig) Option
- func WithWorkspaceGroups(r *model.WorkspaceGroupRegistry) Option
- type RenameActionStepInput
- type SearchKnowledgeInput
- type SetActionStepDoneInput
- type SlackChannelInfo
- type SlackIDToken
- type SlackSyncMode
- type SlackTokenResponse
- type SlackUseCases
- func (uc *SlackUseCases) CleanupOldMessages(ctx context.Context, before time.Time) error
- func (uc *SlackUseCases) HandleActionCreationSubmit(ctx context.Context, actionUC *ActionUseCase, ...) error
- func (uc *SlackUseCases) HandleCaseCreationSubmit(ctx context.Context, caseUC *CaseUseCase, callback *slack.InteractionCallback) error
- func (uc *SlackUseCases) HandleCaseEditSubmit(ctx context.Context, caseUC *CaseUseCase, callback *slack.InteractionCallback) error
- func (uc *SlackUseCases) HandleCommandChoiceSubmit(ctx context.Context, callback *slack.InteractionCallback) (*slack.ModalViewRequest, error)
- func (uc *SlackUseCases) HandleSaveAsDraftClick(ctx context.Context, caseUC *CaseUseCase, callback *slack.InteractionCallback) error
- func (uc *SlackUseCases) HandleSlackEvent(ctx context.Context, event *slackevents.EventsAPIEvent) error
- func (uc *SlackUseCases) HandleSlackMessage(ctx context.Context, msg *slack.Message) error
- func (uc *SlackUseCases) HandleSlashCommand(ctx context.Context, ...) error
- func (uc *SlackUseCases) HandleWorkspaceSelectSubmit(ctx context.Context, callback *slack.InteractionCallback) (*slack.ModalViewRequest, error)
- type SourceUseCase
- func (uc *SourceUseCase) CreateGitHubSource(ctx context.Context, workspaceID string, input CreateGitHubSourceInput) (*model.Source, error)
- func (uc *SourceUseCase) CreateNotionDBSource(ctx context.Context, workspaceID string, input CreateNotionDBSourceInput) (*model.Source, error)
- func (uc *SourceUseCase) CreateNotionPageSource(ctx context.Context, workspaceID string, input CreateNotionPageSourceInput) (*model.Source, error)
- func (uc *SourceUseCase) CreateSlackSource(ctx context.Context, workspaceID string, input CreateSlackSourceInput) (*model.Source, error)
- func (uc *SourceUseCase) DeleteSource(ctx context.Context, workspaceID string, id model.SourceID) error
- func (uc *SourceUseCase) GetSlackChannelNames(ctx context.Context, ids []string) (map[string]string, error)
- func (uc *SourceUseCase) GetSource(ctx context.Context, workspaceID string, id model.SourceID) (*model.Source, error)
- func (uc *SourceUseCase) ListSlackChannels(ctx context.Context) ([]SlackChannelInfo, error)
- func (uc *SourceUseCase) ListSources(ctx context.Context, workspaceID string) ([]*model.Source, error)
- func (uc *SourceUseCase) UpdateGitHubSource(ctx context.Context, workspaceID string, input UpdateGitHubSourceInput) (*model.Source, error)
- func (uc *SourceUseCase) UpdateNotionDBSource(ctx context.Context, workspaceID string, input UpdateNotionDBSourceInput) (*model.Source, error)
- func (uc *SourceUseCase) UpdateNotionPageSource(ctx context.Context, workspaceID string, input UpdateNotionPageSourceInput) (*model.Source, error)
- func (uc *SourceUseCase) UpdateSlackSource(ctx context.Context, workspaceID string, input UpdateSlackSourceInput) (*model.Source, error)
- func (uc *SourceUseCase) UpdateSource(ctx context.Context, workspaceID string, input UpdateSourceInput) (*model.Source, error)
- func (uc *SourceUseCase) ValidateGitHubRepo(ctx context.Context, repository string) (*GitHubRepoValidationResult, error)
- func (uc *SourceUseCase) ValidateNotionDB(ctx context.Context, databaseID string) (*NotionDBValidationResult, error)
- func (uc *SourceUseCase) ValidateNotionPage(ctx context.Context, pageID string) (*NotionPageValidationResult, error)
- type TagUseCase
- func (uc *TagUseCase) CreateTag(ctx context.Context, workspaceID, name string) (*model.Tag, error)
- func (uc *TagUseCase) DeleteTag(ctx context.Context, workspaceID string, id model.TagID) error
- func (uc *TagUseCase) GetTag(ctx context.Context, workspaceID string, id model.TagID) (*model.Tag, error)
- func (uc *TagUseCase) ListTags(ctx context.Context, workspaceID string) ([]*model.Tag, error)
- func (uc *TagUseCase) UpdateTag(ctx context.Context, workspaceID string, id model.TagID, name string) (*model.Tag, error)
- type UpdateActionInput
- type UpdateGitHubSourceInput
- type UpdateKnowledgeInput
- type UpdateMemoInput
- type UpdateNotionDBSourceInput
- type UpdateNotionPageSourceInput
- type UpdateSlackSourceInput
- type UpdateSourceInput
- type UseCases
- func (uc *UseCases) NotionToolClient() notiontool.Client
- func (uc *UseCases) SlackMessageRetriever() slacktool.MessageRetriever
- func (uc *UseCases) SlackSearchService() slacktool.SearchService
- func (uc *UseCases) SlackService() slack.Service
- func (uc *UseCases) ValidateDB(ctx context.Context) (*ValidationResult, error)
- func (uc *UseCases) WebFetchClient() *webfetch.Client
- func (uc *UseCases) WorkspaceGroups() *model.WorkspaceGroupRegistry
- func (uc *UseCases) WorkspaceRegistry() *model.WorkspaceRegistry
- type ValidationIssue
- type ValidationResult
Constants ¶
const ( SlackActionIDStatusSelect = "hc_action_status" SlackActionIDAssigneeSelect = "hc_action_assignee" )
Slack interaction action / block IDs for Action Block Kit messages.
const ( // SlackAgentSessionActionsID is the actionID for the agent session overflow menu. // Slack sends this in block_actions callbacks when any menu option is selected. SlackAgentSessionActionsID = "hc_agent_session_actions" // SlackAgentActionShowSessionInfo is the option value prefix for showing session info modal. // Full value format: "show_session_info:{sessionID}" SlackAgentActionShowSessionInfo = "show_session_info" )
Slack interaction constants for agent session actions
const ( CaseIDKey = "case_id" ActionIDKey = "action_id" ActionStepIDKey = "action_step_id" // MissingFieldIDsKey / MissingFieldNamesKey are populated on // ErrMissingRequiredOnSubmit so the GraphQL error mapper can expose the // list to the frontend (which renders them as the offending inputs). MissingFieldIDsKey = "missing_field_ids" MissingFieldNamesKey = "missing_field_names" // CurrentStatusKey is populated on status-transition errors so the // frontend can tell the user the current state of the case (e.g. "this // draft has already been opened — refresh to see the change"). CurrentStatusKey = "current_status" )
Context keys for error values
const ( SlackCallbackIDSelectWorkspace = "hc_select_workspace" SlackCallbackIDCreateCase = "hc_create_case" SlackCallbackIDEditCase = "hc_edit_case" // SlackCallbackIDCommandChoice is the modal that lets the user pick // "edit case" vs "create action" when /cmd is invoked in a case channel // without an explicit subcommand. The "command" wording (rather than // "action") avoids collision with Slack interactivity's own "action" // concept (block_actions etc.). SlackCallbackIDCommandChoice = "hc_command_choice" // SlackCallbackIDCreateAction is the modal that creates a new Action // (i.e. a task) under the case bound to the current channel. SlackCallbackIDCreateAction = "hc_create_action" SlackBlockIDWorkspaceSelect = "hc_ws_select_block" SlackActionIDWorkspaceRadio = "hc_ws_radio" SlackBlockIDCaseTitle = "hc_case_title_block" SlackActionIDCaseTitle = "hc_case_title" SlackBlockIDCaseDescription = "hc_case_desc_block" SlackActionIDCaseDescription = "hc_case_desc" SlackBlockIDCasePrivate = "hc_case_private_block" SlackActionIDCasePrivate = "hc_case_private" SlackBlockIDCaseAssignees = "hc_case_assignees_block" SlackActionIDCaseAssignees = "hc_case_assignees" // Edit modal's standalone "Options" checkbox group, currently carrying // only the Test-case flag (private/draft are creation-only concerns). SlackBlockIDCaseTest = "hc_case_test_block" SlackActionIDCaseTest = "hc_case_test" // Command choice modal block / action IDs SlackBlockIDCommandChoice = "hc_command_choice_block" SlackActionIDCommandChoice = "hc_command_choice_radio" // Action creation modal block / action IDs SlackBlockIDActionTitle = "hc_action_title_block" SlackActionIDActionTitle = "hc_action_title" SlackBlockIDActionDesc = "hc_action_desc_block" SlackActionIDActionDesc = "hc_action_desc" SlackBlockIDActionAssignee = "hc_action_assignee_input_block" SlackActionIDActionAssignee = "hc_action_assignee_input" SlackBlockIDActionStatusInput = "hc_action_status_input_block" SlackActionIDActionStatusIn = "hc_action_status_input" SlackBlockIDActionDueDate = "hc_action_due_block" SlackActionIDActionDueDate = "hc_action_due" // Save-as-Draft is now offered as a "Draft mode" checkbox inside // the Case creation modal's Options group rather than as a separate // body-level button. These legacy block/action IDs are kept so the // dispatcher can still route any in-flight callbacks emitted before // the layout change to HandleSaveAsDraftClick. SlackBlockIDSaveAsDraftActions = "hc_save_draft_block" SlackActionIDSaveAsDraft = "hc_save_draft_btn" )
Callback IDs for slash command modals
const ( ActionIDDraftSelectWS = "mention_draft_select_ws" ActionIDDraftSubmit = "mention_draft_submit" ActionIDDraftEdit = "mention_draft_edit" ActionIDDraftCancel = "mention_draft_cancel" BlockIDDraftWSSelect = "mention_draft_ws_block" BlockIDDraftActions = "mention_draft_actions" )
PreviewActionIDs identify the buttons inside the preview ephemeral.
const ( // ActionIDDraftQuestionChoice is the action_id of the radio_buttons / // checkboxes element rendering the choices for a single question item. // Same id across all items; per-item disambiguation is done via block_id. ActionIDDraftQuestionChoice = "mention_draft_question_choice" // ActionIDDraftQuestionSubmit is the action_id of the Submit button. // The button's value carries the draft id so the submit handler can // re-enter the draft flow without parsing block_ids. ActionIDDraftQuestionSubmit = "mention_draft_question_submit" // ActionIDDraftQuestionOther is the action_id of the plain_text_input // element rendering the per-item free-form fallback. Same id across all // items; per-item disambiguation is via block_id (item suffix `:other`). ActionIDDraftQuestionOther = "mention_draft_question_other" // ActionIDDraftQuestionFreeText is the action_id of the plain_text_input // element rendering a `free_text` question item's primary control. The // item has no select / checkbox companion; its single multiline input // IS the answer surface, so a distinct action_id keeps the parser path // clean from the per-item Other fallback used by the closed-list // types. ActionIDDraftQuestionFreeText = "mention_draft_question_free_text" // BlockIDDraftQuestionActions is the block_id of the actions block // hosting the Submit button. Distinct from the per-question input // block_ids so dispatch can ignore it when matching answers. BlockIDDraftQuestionActions = "mention_draft_question_actions" // BlockIDDraftQuestionItemPrefix is prepended to each question item's // block_id so the submit handler can recognise (and skip) the actions // block while iterating state values. Item ID follows the prefix. BlockIDDraftQuestionItemPrefix = "mention_draft_question_item:" // BlockIDDraftQuestionOtherSuffix is appended to a per-item block_id to // form the block_id of its free-text fallback InputBlock. Pairing the // fallback against the item is done by stripping this suffix. BlockIDDraftQuestionOtherSuffix = ":other" )
Slack identifiers for the open-mode question form. The action_ids and block_ids are the contract between the rendered Block Kit message and the HTTP interactions controller.
const ActionIDThreadCreateQuestionSubmit = "thread_create_question_submit"
ActionIDThreadCreateQuestionSubmit is the action_id of the Submit button on the thread-mode case-initialization question form. It is distinct from the open-mode (proposal) submit action so the interactions controller routes it to HandleThreadCaseQuestionSubmit. The button value carries the thread TS so the handler can re-resolve the thread without parsing block_ids. The form's per-item input elements reuse the shared open-mode action_ids (ActionIDDraftQuestion*) so the answer parser (parseDraftQuestionAnswers) is shared.
const JobRunLogPageDefaultSize = 20
JobRunLogPageDefaultSize is the page size used when the caller does not specify one (or specifies <= 0). Aligned with the design target for the CaseAgent dashboard run-log table.
const JobRunLogPageMaxSize = 100
JobRunLogPageMaxSize caps the upper bound a caller can request, to keep a single page round-trip small enough to stay snappy.
const SlackCallbackIDDraftEdit = "mention_draft_edit_modal"
SlackCallbackIDDraftEdit is the modal callback_id for the Case-draft Edit modal opened from the preview ephemeral.
Variables ¶
var ( // Not found errors ErrCaseNotFound = errors.New("case not found") ErrActionNotFound = errors.New("action not found") ErrActionStepNotFound = errors.New("action step not found") // Status errors ErrCaseAlreadyClosed = errors.New("case is already closed") ErrCaseAlreadyOpen = errors.New("case is already open") // ErrCaseIsDraft is returned when a status-transition operation (close / // reopen) is invoked on a case that is still in DRAFT. Drafts only leave // DRAFT via SubmitDraft (→ OPEN) or DiscardDraft (delete). ErrCaseIsDraft = errors.New("case is in draft state") // ErrCaseNotDraft is returned by draft-specific operations (Submit / // Discard) when the targeted case is not in DRAFT. ErrCaseNotDraft = errors.New("case is not a draft") // ErrCaseThreadModeUseStatus is returned by CloseCase / ReopenCase when the // targeted case is thread-mode (bound to a Slack thread). Thread-mode cases // change lifecycle by moving the configurable board status via // UpdateCaseStatus, which keeps BoardStatus and the lifecycle Status in sync; // closing / reopening one directly would set Status while leaving BoardStatus // on a mismatched column, desyncing the two. The boundary rejects it so a // mis-wired caller fails loudly instead of producing the inconsistent state. ErrCaseThreadModeUseStatus = errors.New("thread-mode case lifecycle must change via board status") // ErrMissingRequiredOnSubmit is returned by SubmitDraft when the draft // is missing one or more required custom fields. The wrapping goerr // carries the field IDs and human-friendly names (see MissingFieldIDsKey / // MissingFieldNamesKey) so the frontend can point the user at exactly // which inputs to fill. ErrMissingRequiredOnSubmit = errors.New("draft is missing required fields") // ErrDraftTitleRequired is returned by SubmitDraft when the draft was // saved with an empty title. Slack channel naming requires a non-empty // title, so this is enforced at promote time even though Save-as-Draft // accepted the empty value. ErrDraftTitleRequired = errors.New("draft title is required before submit") // ErrFieldValidationFailed wraps a field-level validation failure from // the workspace's field schema (option lookup, type coercion, etc.). // Used so the GraphQL layer can surface "fix the field" as a specific // code without grepping wrapped error messages. ErrFieldValidationFailed = errors.New("field validation failed") // ErrActivationFailed wraps a post-promotion activation failure (Slack // channel creation, channel invites, welcome message). The draft is // rolled back to DRAFT before this error returns, so callers / frontends // should advise "retry submit". ErrActivationFailed = errors.New("case activation failed") // ErrCasePrivateThreadModeUnsupported is returned by the case create flows // when isPrivate=true is requested for a thread-mode workspace. A private // case's only effect is a dedicated private Slack channel, which channel // mode creates and thread mode has no equivalent for (thread-mode cases // reuse the monitored channel and never carry IsPrivate). The frontend // already hides the private toggle in thread mode; the invariant is enforced // here at the usecase boundary so every entry point (GraphQL, Slack modal, // agent tool, import) is covered, not just the web form. ErrCasePrivateThreadModeUnsupported = errors.New("private case is not supported in thread mode") // ErrThreadModeSlackUnconfigured is returned when a thread-mode workspace // must bring a case to OPEN but the Slack service or the monitored channel // is not configured. Thread-mode cases live in the monitored channel's // thread and never provision a dedicated channel, so falling back to the // channel-mode activation path (which would call CreateChannel) is exactly // the invariant violation to avoid. Startup config validation normally // rejects a thread-mode workspace without a monitor channel, so this guards // direct WorkspaceEntry construction (tests / eval) and fails closed. ErrThreadModeSlackUnconfigured = errors.New("thread-mode workspace requires slack service and monitor channel") // ErrCaseThreadModeNoActions is returned by ActionUseCase write paths when // the parent (or reparent target) Case is thread-mode. Thread-mode cases // track progress through the configurable board status (Kanban) and have no // Actions — the configurable status attaches to the Case itself there, while // in channel mode it attaches to Actions (see model.Case.BoardStatus). The // invariant is enforced at the usecase boundary so every entry point // (GraphQL, Slack, agent tools, eval) is covered, not just the agent tool // wiring that withholds the action tools for thread-mode workspaces. ErrCaseThreadModeNoActions = errors.New("thread-mode case cannot have actions") // Action Slack-post state errors ErrSlackMessageAlreadyPosted = errors.New("action already has a Slack message") ErrCaseHasNoSlackChannel = errors.New("parent case has no Slack channel") // Action archive state errors ErrActionAlreadyArchived = errors.New("action is already archived") ErrActionNotArchived = errors.New("action is not archived") // Access control errors ErrAccessDenied = errors.New("access denied to private case") // Other errors ErrDuplicateField = errors.New("duplicate field") // ErrUnknownUser is returned by a case write when an assignee id or a // user / multi-user field value references a user that does not exist in // the SlackUser store. It guards against an agent (or API client) // persisting a hallucinated / mistyped user id. Slack sync delay is // treated as non-existence per project policy. ErrUnknownUser = errors.New("unknown user") // ErrInvalidArgument is returned by usecase methods when the caller // provides input that violates a domain invariant (unknown ID, list // element that does not belong to the workspace, etc.). Distinct from // ErrAccessDenied / ErrNotFound so the GraphQL layer can map it to // BAD_USER_INPUT rather than INTERNAL. ErrInvalidArgument = errors.New("invalid argument") )
Sentinel errors for use case layer
var DefaultThreadcaseBudget = planexec.BudgetConfig{
PlannerLoopMax: 8,
SubAgentLoopMax: 20,
}
DefaultThreadcaseBudget is the planexec budget used for thread-mode agent turns when AgentDeps.ThreadcaseBudget is unset. Conservative bounds keep a mention turn responsive while allowing a couple of investigation rounds.
var ErrGitHubNotConfigured = goerr.New("GitHub App is not configured")
ErrGitHubNotConfigured is returned when GitHub App is not configured
var ErrImportFieldSchemaStale = goerr.New("workspace field schema has changed since import was created")
ErrImportFieldSchemaStale is returned by ImportUseCase.Execute when the workspace field schema has changed since createCaseImport. The session.Issues will be appended with per-field details.
var ErrImportSessionInvalidState = goerr.New("import session is not in pending state")
ErrImportSessionInvalidState is returned by ImportUseCase.Execute when the target session is not in pending state.
var ErrImportSessionNotFound = goerr.New("import session not found")
ErrImportSessionNotFound is returned by ImportUseCase.Get when no session matches the given ID or the caller is not the creator.
var ErrImportValidation = goerr.New("import session has validation errors")
ErrImportValidation is returned by ImportUseCase.Execute when the session has unresolved error-severity issues from preview.
var ErrInferenceInProgress = errors.New("draft inference in progress")
ErrInferenceInProgress is returned when an interaction tries to operate on a draft whose Materializer call is still in flight.
var ErrKnowledgeInput = goerr.New("invalid knowledge input")
ErrKnowledgeInput is returned when create/update input fails validation at the usecase entry point (before any persistence).
var ErrMemoNotEnabled = goerr.New("memo feature is not enabled for this workspace")
ErrMemoNotEnabled is returned when a memo write targets a workspace that has not configured the memo feature (no [memo] field schema).
var ErrMemoNotFound = goerr.New("memo not found")
ErrMemoNotFound is returned when a memo cannot be located within its Case.
var ErrNoAccessibleWorkspace = errors.New("no accessible workspace for user")
ErrNoAccessibleWorkspace is returned when the mentioning user has no workspace they can create a Case in.
var ErrTagInUse = goerr.New("tag is in use")
ErrTagInUse is returned when deleting a tag that is still referenced by at least one knowledge entry. The delete is refused so no dangling reference can be created.
var ErrUnauthenticated = goerr.New("unauthenticated")
ErrUnauthenticated is returned by the dashboard "my *" queries when no auth token is present. Unlike ListCases (which treats a missing token as a system/bot context that bypasses per-user filtering), the home aggregation is meaningless without an identity, so it fails loudly instead.
var ErrUnknownTag = goerr.New("unknown tag id")
ErrUnknownTag is returned when a knowledge create/update references a tag id that does not exist in the workspace. The operation is rejected wholesale — no partial write occurs.
Functions ¶
func NewActionStepToolAdapter ¶
func NewActionStepToolAdapter(uc *ActionStepUseCase) core.ActionStepMutator
NewActionStepToolAdapter returns a core.ActionStepMutator backed by the supplied ActionStepUseCase. Returns nil when uc is nil, matching the contract that core.Deps.ActionStepUC == nil → tool fails loudly.
func NewActionToolAdapter ¶
func NewActionToolAdapter(uc *ActionUseCase) core.ActionMutator
NewActionToolAdapter returns a core.ActionMutator backed by the supplied ActionUseCase. Returns nil when uc is nil, matching the contract that core.Deps.ActionUC == nil → tool fails loudly.
func NewCaseMultiActionAdapter ¶
func NewCaseMultiActionAdapter(action *ActionUseCase, step *ActionStepUseCase) casemulti.ActionUsecase
NewCaseMultiActionAdapter returns a casemulti.ActionUsecase backed by the action + action-step usecases, or nil when either is nil (which disables the casemulti action tools while leaving the case-level tools working).
func NewCaseMultiCaseAdapter ¶
func NewCaseMultiCaseAdapter(uc *CaseUseCase) casemulti.CaseUsecase
NewCaseMultiCaseAdapter returns a casemulti.CaseUsecase backed by uc, or nil when uc is nil so hosts can wire casemulti unconditionally (a nil CaseUC makes casemulti.New return no tools).
func NewCaseToolAdapter ¶
func NewCaseToolAdapter(uc *CaseUseCase) casewriter.CaseMutator
NewCaseToolAdapter wraps a CaseUseCase as a casewriter.CaseMutator. Returns nil when uc is nil so callers can pass the result straight through to casewriter.Deps (a nil mutator disables the tool, which fails loudly at runtime rather than silently degrading).
func NewKnowledgeToolAccessor ¶
func NewKnowledgeToolAccessor(uc *KnowledgeUseCase, tagUC *TagUseCase) knowledgetool.KnowledgeAccessor
NewKnowledgeToolAccessor returns the read surface backed by the use cases. Returns nil when either use case is nil so the tool wiring can detect an unconfigured knowledge feature.
func NewKnowledgeToolMutator ¶
func NewKnowledgeToolMutator(uc *KnowledgeUseCase, tagUC *TagUseCase) knowledgetool.KnowledgeMutator
NewKnowledgeToolMutator returns the write surface backed by the use cases. Returns nil when either use case is nil.
func NewMemoToolAdapter ¶
func NewMemoToolAdapter(uc *MemoUseCase) memotool.MemoMutator
NewMemoToolAdapter returns a memotool.MemoMutator backed by the supplied MemoUseCase. Returns nil when uc is nil so the tool wiring can detect an unconfigured memo feature.
func ParseAgentActionValue ¶
ParseAgentActionValue parses an agent action option value into action type and data. Format: "{action}:{data}" (e.g., "show_session_info:uuid-value")
func ParseSlackAssigneeBlockID ¶
ParseSlackAssigneeBlockID parses a block_id of the form "{prefix}:{workspaceID}:{actionID}" into its components.
func ParseSlackStatusSelectValue ¶
func ParseSlackStatusSelectValue(value string) (workspaceID string, actionID int64, status types.ActionStatus, err error)
ParseSlackStatusSelectValue parses a status_select option value of the form "{workspaceID}:{actionID}:{status}" and returns its components.
func SlackActionAssigneeBlockID ¶
SlackActionAssigneeBlockID returns the block_id that wraps the users_select element. We encode (workspaceID, actionID) into the block_id because users_select callbacks carry no `value` field.
Types ¶
type ActionStepUseCase ¶
type ActionStepUseCase struct {
// contains filtered or unexported fields
}
ActionStepUseCase orchestrates ActionStep CRUD: load parent Action and Case, enforce private-case access control, persist the step, record an ActionEvent, and post a thread context-block notification to Slack.
func NewActionStepUseCase ¶
func NewActionStepUseCase(repo interfaces.Repository, slackService slack.Service, slotCoord *notificationSlotCoordinator) *ActionStepUseCase
NewActionStepUseCase constructs the ActionStepUseCase. slotCoord may be nil; when nil (or its slotDuration is non-positive), step change notifications fall back to the legacy reply_broadcast path.
func (*ActionStepUseCase) Add ¶
func (uc *ActionStepUseCase) Add(ctx context.Context, in AddActionStepInput) (*model.ActionStep, error)
Add creates a new ActionStep under the given Action.
func (*ActionStepUseCase) Delete ¶
func (uc *ActionStepUseCase) Delete(ctx context.Context, in DeleteActionStepInput) error
Delete removes a step. Returns nil even if the step did not exist (idempotent) but only after access control is satisfied.
func (*ActionStepUseCase) List ¶
func (uc *ActionStepUseCase) List(ctx context.Context, workspaceID string, actionID int64) ([]*model.ActionStep, error)
List returns all steps for the given Action, ordered oldest first. Returns an empty list when the caller cannot access the parent Case.
func (*ActionStepUseCase) Progress ¶
func (uc *ActionStepUseCase) Progress(ctx context.Context, workspaceID string, actionID int64) (int, int, error)
Progress returns (done, total) for the given Action's steps. Both are 0 when the parent Case is inaccessible to the caller.
func (*ActionStepUseCase) Rename ¶
func (uc *ActionStepUseCase) Rename(ctx context.Context, in RenameActionStepInput) (*model.ActionStep, error)
Rename updates the step's title. No-op (returns the existing step untouched) when the trimmed title equals the current one — no ActionEvent is recorded and no Slack notification is sent in that case.
func (*ActionStepUseCase) SetDone ¶
func (uc *ActionStepUseCase) SetDone(ctx context.Context, in SetActionStepDoneInput) (*model.ActionStep, error)
SetDone toggles the step's done state. No-op (returns the existing step untouched) if the requested state is already in effect.
type ActionUseCase ¶
type ActionUseCase struct {
// contains filtered or unexported fields
}
func NewActionUseCase ¶
func NewActionUseCase(repo interfaces.Repository, registry *model.WorkspaceRegistry, slackService slack.Service, baseURL string, slotCoord *notificationSlotCoordinator) *ActionUseCase
NewActionUseCase constructs the ActionUseCase. slotCoord may be nil; when nil (or when its slotDuration is non-positive), channel-side change notifications fall back to the legacy reply_broadcast path on each post.
func (*ActionUseCase) ArchiveAction ¶
func (uc *ActionUseCase) ArchiveAction(ctx context.Context, workspaceID string, id int64, actor ActorRef) (*model.Action, error)
ArchiveAction marks an action as archived so it disappears from default listings (Kanban, Case detail). Archived actions can be unarchived later via UnarchiveAction. The action document itself is preserved; only the public lifecycle hides it. Idempotency: archiving an already-archived action returns ErrActionAlreadyArchived rather than silently succeeding, because callers should distinguish "already done" from "now done" for UI feedback.
func (*ActionUseCase) BulkArchiveActions ¶
func (uc *ActionUseCase) BulkArchiveActions(ctx context.Context, workspaceID string, ids []int64, actor ActorRef) ([]*model.Action, error)
BulkArchiveActions archives the given actions by delegating each id to ArchiveAction, so bulk and single archive share the exact same path (access control, idempotency, event recording, Slack notification). The archive body lives only in ArchiveAction and is never duplicated here, so any future change to single-archive behaviour automatically applies to bulk.
Idempotency: ids that are already archived are skipped rather than failing the whole batch, since "archive everything in this column" should tolerate rows that someone else already archived. Any other error (access denied, not found, persistence failure) is propagated — bulk archive must not silently swallow a real failure. The returned slice contains only the actions that were newly archived.
func (*ActionUseCase) BulkArchiveActionsAsync ¶
func (uc *ActionUseCase) BulkArchiveActionsAsync(ctx context.Context, workspaceID string, ids []int64, actor ActorRef)
BulkArchiveActionsAsync runs BulkArchiveActions in the background via async.Dispatch so the operation outlives the HTTP request that triggered it. Clearing a completed column issues one ArchiveAction (DB write + event + Slack post) per action; on a large column that can take longer than the client is willing to wait, and a mid-flight disconnect would otherwise cancel the request context and leave the column half-archived. async.Dispatch hands the work a context with the auth token / logger intact but the cancellation severed, so the whole column is archived even after the GraphQL response (the accepted ids) has been returned. Per-action failures surface through errutil.Handle inside the synchronous core rather than to the caller, which has already returned.
func (*ActionUseCase) CreateAction ¶
func (*ActionUseCase) GetAction ¶
func (uc *ActionUseCase) GetAction(ctx context.Context, workspaceID string, id int64, opts ...interfaces.ActionListOptions) (*model.Action, error)
GetAction returns the action by ID. opts is variadic and optional: existing callers pass none and get the action regardless of its parent Case's privacy (archive scope is irrelevant to a single Get). When the first opts element has ExcludePrivateCaseActions set, the parent Case is loaded and an action belonging to a private Case is reported as ErrAccessDenied — the MCP endpoint relies on this so private-case actions are never returned.
func (*ActionUseCase) GetActions ¶
func (uc *ActionUseCase) GetActions(ctx context.Context, workspaceID string, ids []int64, opts interfaces.ActionListOptions) ([]*model.Action, error)
GetActions retrieves multiple actions by ID in a single repository batch (GetByIDs) and applies the same parent-Case access control as the listing methods, avoiding the N+1 round-trips a per-ID loop would incur. Results preserve the order of ids; ids that do not resolve — and actions whose parent Case is excluded (private under opts.ExcludePrivateCaseActions, or inaccessible to the caller) — are omitted.
func (*ActionUseCase) GetActionsByCase ¶
func (uc *ActionUseCase) GetActionsByCase(ctx context.Context, workspaceID string, caseID int64, opts interfaces.ActionListOptions) ([]*model.Action, error)
func (*ActionUseCase) ListActions ¶
func (uc *ActionUseCase) ListActions(ctx context.Context, workspaceID string, opts interfaces.ActionListOptions) ([]*model.Action, error)
func (*ActionUseCase) ListOpenCaseActions ¶
func (uc *ActionUseCase) ListOpenCaseActions(ctx context.Context, workspaceID string) ([]*model.Action, error)
ListOpenCaseActions returns all actions belonging to cases with OPEN status.
func (*ActionUseCase) PostSlackMessageToAction ¶
func (uc *ActionUseCase) PostSlackMessageToAction(ctx context.Context, workspaceID string, actionID int64) (*model.Action, error)
PostSlackMessageToAction posts the Action's primary Slack message and persists the resulting timestamp on the Action. It exists for two callers that operate on actions whose initial CreateAction post never reached Slack:
- The WebUI "Post to Slack" button on actions whose SlackMessageTS is empty (e.g. the action was created before the tool path was unified with the usecase).
- The diagnosis fix-unsent-action job, which sweeps such actions in bulk.
Unlike CreateAction's best-effort tail, this method is strict: a missing Slack channel, an already-posted action, or a Slack/PostMessage error surface as typed errors so the caller can react. Callers that want CreateAction-style "log and move on" behaviour should call CreateAction instead.
func (*ActionUseCase) UnarchiveAction ¶
func (uc *ActionUseCase) UnarchiveAction(ctx context.Context, workspaceID string, id int64, actor ActorRef) (*model.Action, error)
UnarchiveAction restores a previously archived action back to active state.
func (*ActionUseCase) UpdateAction ¶
func (uc *ActionUseCase) UpdateAction(ctx context.Context, workspaceID string, in UpdateActionInput) (*model.Action, error)
UpdateAction is the single entry point for mutating an Action. All transports (GraphQL/WebUI, Slack interactivity, internal callers) funnel through this method; Slack side-effects are controlled by in.SlackSync and in.Actor.
type ActorRef ¶
ActorRef identifies the actor that triggered an update, for change-notification rendering.
type AddActionStepInput ¶
AddActionStepInput is the input for ActionStepUseCase.Add.
type AgentDeps ¶
type AgentDeps struct {
Repo interfaces.Repository // required
Registry *model.WorkspaceRegistry // required
LLM gollem.LLMClient // required
// HistoryRepo and TraceRepo are required: the agent session flow persists
// gollem.History across mentions and writes a trace for each Execute. Pass
// agentarchive.NewMemoryHistoryRepository / NewMemoryTraceRepository in tests.
HistoryRepo gollem.HistoryRepository
TraceRepo trace.Repository
// ActionUC is required: the core__create_action tool routes through it so
// all Action create paths share the same usecase implementation.
// ActionStepUC follows the same contract for the core__*_action_step
// tool family.
ActionUC *ActionUseCase
ActionStepUC *ActionStepUseCase
// MemoUC backs the Case-scoped memo tools (memo__*) in case-bound mode.
// Optional: nil means the agent gets no memo tools (e.g. the workspace has
// not enabled memos, or memos are intentionally withheld).
MemoUC *MemoUseCase
// KnowledgeUC backs the workspace-wide knowledge tools. Optional: nil means
// the agent gets no knowledge tools.
KnowledgeUC *KnowledgeUseCase
// TagUC backs the workspace-wide tag tools (and tag existence checks). It is
// required alongside KnowledgeUC for any knowledge tools to be wired.
TagUC *TagUseCase
// CaseUC is required for thread mode: the thread-case orchestrator applies
// the agent's materialize / close decisions through it so every case
// mutation funnels through the single CaseUseCase entry point.
CaseUC *CaseUseCase
// ThreadcaseBudget overrides the planexec budget for the thread-mode
// agent. Zero values fall back to DefaultThreadcaseBudget.
ThreadcaseBudget planexec.BudgetConfig
// Optional Slack tool clients. SlackService is the Bot-token client;
// SlackSearch and SlackRetriever sit on the User OAuth Token.
SlackService slack.Service
SlackSearch slacktool.SearchService
SlackRetriever slacktool.MessageRetriever
// Optional integrations.
NotionTool notiontool.Client
GitHubClient *githubtool.Client
WebFetchClient *webfetch.Client
EmbedClient interfaces.EmbedClient
// JiraTools carries the already-expanded Jira read tools (see
// pkg/agent/tool/jira / agent.CommonDeps.JiraTools for why this is a
// plain tool slice rather than a client type). nil/empty means Jira is
// not configured.
JiraTools []gollem.Tool
}
AgentDeps groups the dependencies AgentUseCase needs. Required fields are marked below; optional ones can be left zero to disable the corresponding tool or behaviour.
SlackRetriever, when supplied, switches slack__get_messages to a User-token- backed read path so public channels can be fetched without bot membership.
type AgentUseCase ¶
type AgentUseCase struct {
// contains filtered or unexported fields
}
AgentUseCase is the Slack-side orchestrator for case-bound mention turns. It resolves the request (bot user id, case lookup, conversation snapshot, etc.) and hands off to the casebound runtime (pkg/usecase/agent/casebound) which owns gollem invocation, system prompt assembly, and the turn lock lifecycle.
func NewAgentUseCase ¶
func NewAgentUseCase(deps AgentDeps) *AgentUseCase
NewAgentUseCase creates a new AgentUseCase from a deps bundle. See AgentDeps.
func (*AgentUseCase) HandleAgentMention ¶
func (uc *AgentUseCase) HandleAgentMention(ctx context.Context, msg *slackmodel.Message) error
HandleAgentMention processes an app_mention event and responds with an AI agent
func (*AgentUseCase) HandleSessionInfoRequest ¶
func (uc *AgentUseCase) HandleSessionInfoRequest(ctx context.Context, triggerID, sessionID string) error
HandleSessionInfoRequest opens a modal displaying the session ID
func (*AgentUseCase) HandleThreadCaseCreation ¶
func (uc *AgentUseCase) HandleThreadCaseCreation(ctx context.Context, msg *slackmodel.Message, entry *model.WorkspaceEntry) error
HandleThreadCaseCreation processes a channel-root post (by a human or an integration bot) in a thread-mode monitored channel — the ONLY trigger that initiates case creation. For a bot-relayed post the reporter is best-effort resolved from the first Slack user mention in the body, and stays empty when none is present (thread-mode cases may have no reporter). It does NOT create a case immediately: it runs the initialization (create) agent, which investigates, may ask the user, and only commits a validated case once it is confident. On success it posts a Block Kit summary; on a question it posts an interactive form and waits; on fallback it posts a "couldn't conclude" message. Resuming after a question is driven by the question form's Submit interaction (HandleThreadCaseQuestionSubmit) — a free-text reply or mention in the not-yet-a-case thread is intentionally ignored.
func (*AgentUseCase) HandleThreadCaseMention ¶
func (uc *AgentUseCase) HandleThreadCaseMention(ctx context.Context, msg *slackmodel.Message, entry *model.WorkspaceEntry, foundCase *model.Case) error
HandleThreadCaseMention processes an app_mention inside a thread-mode case thread: it runs the investigation agent and applies the resulting decision (respond / materialize / close).
func (*AgentUseCase) HandleThreadCaseMentionCreation ¶
func (uc *AgentUseCase) HandleThreadCaseMentionCreation(ctx context.Context, msg *slackmodel.Message, entry *model.WorkspaceEntry) error
HandleThreadCaseMentionCreation starts (or resumes) a thread-mode Case from an @mention in a monitored channel that has no Case yet. It is the mention-trigger counterpart of HandleThreadCaseCreation: the mention — at the channel root or inside a case-less thread — is the creation trigger, and the mention text is folded into the create agent's seed. The bot-authored / accept_bot gate is applied by the caller (handleThreadModeEvent) before this runs.
The first mention on a thread seeds a fresh creation turn; a channel-root mention seeds the mention text alone (like instant), while an in-thread mention seeds the whole thread (root + replies + this mention). A follow-up mention while the thread is still not a Case resumes the in-flight session, superseding any pending question with the new intent (mirrors ResumeThreadCaseCreation). Per-thread serialization comes from the turn lock keyed on (channel, threadTS); TriggerTS is the mention's own TS so a re-delivered mention dedups without a follow-up being mistaken for a retry.
func (*AgentUseCase) HandleThreadCaseQuestionSubmit ¶
func (uc *AgentUseCase) HandleThreadCaseQuestionSubmit(ctx context.Context, callback *goslack.InteractionCallback, action *goslack.BlockAction) error
HandleThreadCaseQuestionSubmit is the Submit-button entry point for the thread-mode case-initialization question form. It validates the answer against the pending snapshot, swaps the form into a read-only "answered" record, clears the pending question, and resumes the create agent with the formatted answers as the next-turn input. Missing answers re-render the form with an inline error.
func (*AgentUseCase) HandleWorkspaceAgentMention ¶ added in v0.2.0
func (uc *AgentUseCase) HandleWorkspaceAgentMention(ctx context.Context, msg *slackmodel.Message, entry *model.WorkspaceEntry) error
HandleWorkspaceAgentMention processes an app_mention that should run the workspace-level cross-case agent (wsagent) on behalf of the mentioning user, then posts the reply into the mention's thread. The session is case-less (CaseID == 0) and tagged SessionKindWorkspaceAgent: the agent operates across every case the user can access, not one bound case.
Both hosts of the workspace agent funnel through here:
- channel mode — a mention in the configured [slack] workspace_channel.
- thread mode — a channel-root mention in the monitored channel (with trigger = "mention"), plus every follow-up mention inside the thread it opened. Those threads never become Cases; the Session's Kind is what the dispatcher reads to keep them out of the case-creation path.
func (*AgentUseCase) ResumeThreadCaseCreation ¶
func (uc *AgentUseCase) ResumeThreadCaseCreation(ctx context.Context, msg *slackmodel.Message, entry *model.WorkspaceEntry) error
ResumeThreadCaseCreation continues the initialization (create) agent on a thread that has no case yet, with msg as the latest user intent; the conversation history (keyed on Session.ID) carries the prior turn's investigation and question. In production this is reached only through the offline eval harness — the live Slack flow resumes a deferred question via the question form's Submit interaction, and free-text replies / mentions in a not-yet-a-case thread are ignored (see handleThreadModeEvent).
type AssistDeps ¶
type AssistDeps struct {
Repo interfaces.Repository // required
Registry *model.WorkspaceRegistry // required
LLM gollem.LLMClient // required
// ActionUC routes core__create_action through the unified usecase entry
// point so assist-driven creates trigger the same Slack post and event
// records as GraphQL/Slack-modal creates. Required.
ActionUC *ActionUseCase
// CaseUC backs the case_ref read tools
// (core__search_referenceable_cases / core__get_referenceable_cases).
// Optional: nil disables those tools (no case_ref fields configured).
CaseUC *CaseUseCase
// Optional Slack tool clients. SlackService is the Bot-token client;
// SlackSearch and SlackRetriever sit on the User OAuth Token.
SlackService slack.Service
SlackSearch slacktool.SearchService
SlackRetriever slacktool.MessageRetriever
// Optional integrations.
NotionTool notiontool.Client
GitHubClient *githubtool.Client
WebFetchClient *webfetch.Client
EmbedClient interfaces.EmbedClient
// JiraTools carries the already-expanded Jira read tools (see
// pkg/agent/tool/jira). Unlike NotionTool/GitHubClient/WebFetchClient
// this is not a client type: the Jira integration is a gollem.ToolSet
// with no exported ToolSet-to-[]Tool helper, so config.Jira.Configure
// expands it once at startup and hands the result through as a plain
// tool slice. nil/empty means Jira is not configured.
JiraTools []gollem.Tool
}
AssistDeps groups the dependencies AssistUseCase needs. Required fields are marked below; the rest can be left zero to disable the corresponding tool or behaviour.
SlackRetriever, when supplied, lets slack__get_messages read public channels without bot membership via the User token (Slack contract: only user tokens can access public channels they are not in).
type AssistOption ¶
AssistOption holds options for the assist command
type AssistUseCase ¶
type AssistUseCase struct {
// contains filtered or unexported fields
}
AssistUseCase handles periodic AI-powered case assistance
func NewAssistUseCase ¶
func NewAssistUseCase(deps AssistDeps) *AssistUseCase
NewAssistUseCase creates a new AssistUseCase from a deps bundle. See AssistDeps.
func (*AssistUseCase) RunAssist ¶
func (uc *AssistUseCase) RunAssist(ctx context.Context, opts AssistOption) error
RunAssist iterates all workspaces and open cases, running the assist agent for each
type AuthOption ¶
type AuthOption func(*AuthUseCase)
AuthOption is a functional option for AuthUseCase
func WithBotToken ¶
func WithBotToken(botToken string) AuthOption
WithBotToken sets the Slack bot token
type AuthUseCase ¶
type AuthUseCase struct {
// contains filtered or unexported fields
}
func NewAuthUseCase ¶
func NewAuthUseCase(repo interfaces.Repository, clientID, clientSecret, callbackURL string, options ...AuthOption) *AuthUseCase
func (*AuthUseCase) GetAuthURL ¶
func (uc *AuthUseCase) GetAuthURL(state string) string
GetAuthURL returns the URL for Slack OAuth
func (*AuthUseCase) HandleCallback ¶
HandleCallback processes the OAuth callback
func (*AuthUseCase) IsNoAuthn ¶
func (uc *AuthUseCase) IsNoAuthn() bool
IsNoAuthn returns false for regular AuthUseCase
func (*AuthUseCase) ValidateToken ¶
func (uc *AuthUseCase) ValidateToken(ctx context.Context, tokenID auth.TokenID, tokenSecret auth.TokenSecret) (*auth.Token, error)
ValidateToken validates the token and returns user info
type AuthUseCaseInterface ¶
type AuthUseCaseInterface interface {
GetAuthURL(state string) string
HandleCallback(ctx context.Context, code string) (*auth.Token, error)
ValidateToken(ctx context.Context, tokenID auth.TokenID, tokenSecret auth.TokenSecret) (*auth.Token, error)
Logout(ctx context.Context, tokenID auth.TokenID) error
IsNoAuthn() bool // Added to identify NoAuthnUseCase
}
AuthUseCaseInterface defines the interface for authentication use cases
type CaseEventPublisher ¶
type CaseEventPublisher interface {
PublishCaseLifecycle(ctx context.Context, workspaceID string, c *model.Case, lifecycle model.CaseLifecycle, actorUserID string)
}
CaseEventPublisher is the narrow surface of pkg/usecase/job.UseCase that CaseUseCase calls into after a lifecycle transition. The interface is defined here so this package does not import pkg/usecase/job (which would create a cycle: job → usecase → job).
type CaseUpdate ¶
type CaseUpdate struct {
Title *string
Description *string
// IsTest, when non-nil, sets the test flag; nil preserves the stored value.
// A pointer is required to distinguish "leave unchanged" from "set false".
IsTest *bool
// nil means "preserve all stored field values". A non-nil map merges its
// entries on top of the existing values (callers cannot remove individual
// entries via this API).
Fields map[string]model.FieldValue
}
CaseUpdate represents a partial update to a Case. Each pointer/slice is nil-vs-set: nil means "preserve the existing value", a non-nil pointer means "set to this value (including empty string)". For Fields the nil case preserves all stored field values; a non-nil map merges the supplied entries on top of the existing ones (entries are not removed individually — clients should send the empty value to clear a field if needed).
Assignees are intentionally NOT part of this patch. They are mutated only through the dedicated AssignCase / UnassignCase delta operations, so every entry point shares one race-free path and a full-list replace can never silently clobber a concurrent edit.
type CaseUseCase ¶
type CaseUseCase struct {
// contains filtered or unexported fields
}
func NewCaseUseCase ¶
func NewCaseUseCase(repo interfaces.Repository, registry *model.WorkspaceRegistry, slackService slack.Service, slackAdminService slack.AdminService, baseURL string) *CaseUseCase
func (*CaseUseCase) AssignCase ¶
func (uc *CaseUseCase) AssignCase(ctx context.Context, workspaceID string, id int64, userIDs []string) (*model.Case, error)
AssignCase atomically adds the given Slack user IDs to the case's assignee set. Unlike UpdateCase — which replaces the whole assignee list and therefore loses a concurrent edit inside its read-modify-write window — the add is applied as a transactional set union in the repository, so two simultaneous "assign me" actions both land. IDs already assigned are ignored. New assignees must resolve to known Slack users. An empty userIDs slice is a no-op that returns the case unchanged.
func (*CaseUseCase) CaseURL ¶
func (uc *CaseUseCase) CaseURL(workspaceID string, caseID int64) string
CaseURL returns the web-UI URL for a specific case detail page, or an empty string when no baseURL has been configured.
func (*CaseUseCase) CreateCase ¶
func (uc *CaseUseCase) CreateCase(ctx context.Context, workspaceID string, title, description string, assigneeIDs []string, fieldValues map[string]model.FieldValue, isPrivate bool, isTest bool, sourceTeamID string, requestKey string) (*model.Case, error)
CreateCase persists a brand-new case in status=OPEN and runs the mode- appropriate activation (dedicated Slack channel in channel mode, monitored- channel thread in thread mode). It is the public entry point used by the createCase mutation and the slash-command "submit" flow. The mode decision is delegated to the shared funnel openInWorkspaceMode so every OPEN-case path honours the same invariant.
func (*CaseUseCase) CreateDraft ¶
func (uc *CaseUseCase) CreateDraft(ctx context.Context, workspaceID string, title, description string, assigneeIDs []string, fieldValues map[string]model.FieldValue, isPrivate bool, isTest bool) (*model.Case, error)
CreateDraft persists a case in status=DRAFT — i.e. an "in-progress" entry saved from the Slack creation modal's Save as Draft button. None of the activation side effects (Slack channel, invites, welcome, etc.) run; those fire only when the draft is later promoted via SubmitDraft.
The reporter (auth-context Slack user) becomes the draft owner; the returned case carries the assigned ID so the caller can echo it back to the user.
func (*CaseUseCase) DeleteCase ¶
func (*CaseUseCase) DiscardDraft ¶
DiscardDraft permanently deletes a draft. Public drafts are team-wide shared so any workspace member may discard one; private drafts are hidden from non-reporters at the GetDraft layer, which naturally keeps them owner-only. Non-draft cases are rejected so callers cannot pivot this method into a "delete any case" shortcut.
func (*CaseUseCase) GetActionStatusSet ¶
func (uc *CaseUseCase) GetActionStatusSet(workspaceID string) *model.ActionStatusSet
GetActionStatusSet returns the resolved ActionStatusSet for the workspace, falling back to the legacy default when the workspace is unknown or has no custom configuration. This is the canonical accessor for any layer that needs to render or validate action statuses outside ActionUseCase.
func (*CaseUseCase) GetCaseStatusSet ¶
func (uc *CaseUseCase) GetCaseStatusSet(workspaceID string) *model.ActionStatusSet
GetCaseStatusSet returns the configurable Case status set (the Kanban columns) for a thread-mode workspace, or nil for channel-mode workspaces.
func (*CaseUseCase) GetCases ¶
func (uc *CaseUseCase) GetCases(ctx context.Context, workspaceID string, ids []int64) ([]*model.Case, error)
GetCases retrieves multiple cases by ID in a single batch, applying the same per-case access control as GetCase. It fetches all requested cases with one repository batch call (repo.Case().GetByIDs) to avoid N+1 round-trips, then:
- omits cases that do not exist;
- omits private drafts the caller did not author (their existence must not leak);
- RestrictCases non-draft private cases the caller cannot access.
Results preserve the order of ids; duplicate ids yield duplicate entries.
func (*CaseUseCase) GetDraft ¶
func (uc *CaseUseCase) GetDraft(ctx context.Context, workspaceID string, id int64) (*model.Case, error)
GetDraft returns a single draft case. Public drafts are visible workspace-wide so any team member can preview (and act on) an in-progress entry; private drafts remain reporter-only (the usual ChannelUserIDs check can't help yet — the draft has no Slack channel). Non-draft cases return ErrCaseNotDraft so callers cannot reuse the draft resolver to peek at submitted cases.
Mutating actions (SubmitDraft, DiscardDraft) reach the draft through this method, so private-draft access control automatically extends to them: a non-reporter cannot even discover a private draft, let alone modify it. Public drafts are deliberately open — the team owns them.
func (*CaseUseCase) GetFieldConfiguration ¶
func (uc *CaseUseCase) GetFieldConfiguration(workspaceID string) *config.FieldSchema
func (*CaseUseCase) GetReferenceableCases ¶
func (uc *CaseUseCase) GetReferenceableCases(ctx context.Context, workspaceID string, ids []int64) ([]*model.Case, error)
GetReferenceableCases batch-fetches the full Cases for the given IDs in workspaceID, returning only those that are referenceable (non-private, non-draft, existing). IDs that are missing / private / draft are omitted, so the caller can diff the input against the result to report them. Results preserve the input ID order. This backs the agent's detail-fetch tool.
func (*CaseUseCase) ListCases ¶
func (uc *CaseUseCase) ListCases(ctx context.Context, workspaceID string, status *types.CaseStatus) ([]*model.Case, error)
func (*CaseUseCase) ListDrafts ¶
ListDrafts returns every draft case in the workspace. Drafts are workspace-wide so any team member can pick one up; private drafts are the exception and remain visible only to their reporter (a draft has no Slack channel yet, so the usual IsCaseAccessible check via ChannelUserIDs would lock everyone out — we use ReporterID instead).
func (*CaseUseCase) ListReferenceableCases ¶
func (uc *CaseUseCase) ListReferenceableCases(ctx context.Context, workspaceID, query string, limit int) ([]model.CaseRef, error)
ListReferenceableCases returns the non-private, non-draft Cases of workspaceID as case_ref candidates. Unlike ListCases, private Cases are dropped entirely (never RestrictCase'd) so a picker cannot even reveal that a private Case exists — the project rule that private Cases are not referenceable. With an empty query, OPEN cases sort first, then by most recently updated. With a query, results match the Case title (substring, case-insensitive) or the Case ID ("#42" / "42"), sorted by most recently updated. At most limit (clamped to referenceableCasesLimit) rows are returned. DRAFT cases are excluded because List excludes them by default.
func (*CaseUseCase) MaterializeThreadCase ¶
func (uc *CaseUseCase) MaterializeThreadCase(ctx context.Context, workspaceID string, id int64, title, description string, fieldValues map[string]model.FieldValue) (*model.Case, error)
MaterializeThreadCase applies the LLM-materialized title / description / custom field values onto a thread-mode Case. Empty title / description are ignored (the placeholder set at creation is kept). Field values are type-checked via the workspace validator before write.
func (*CaseUseCase) ReferenceWorkspaceForField ¶
func (uc *CaseUseCase) ReferenceWorkspaceForField(workspaceID, fieldID string) (string, error)
ReferenceWorkspaceForField returns the reference_workspace configured for the case_ref field fieldID in workspaceID. It errors when the field is unknown or is not a case_ref type, so an agent tool that was handed a wrong field id fails loudly instead of querying the wrong workspace.
func (*CaseUseCase) RenderCaseFieldValues ¶
func (uc *CaseUseCase) RenderCaseFieldValues(ctx context.Context, workspaceID string, fieldValues map[string]model.FieldValue) (map[string]any, error)
RenderCaseFieldValues flattens a Case's field values into a plain map for an agent tool response. Non-reference fields render their raw stored value (as the existing tool responses do). Case-reference fields are resolved one level — each referenced Case ID becomes {id, title, status} — using the field's configured reference_workspace. An ID that no longer resolves (the referenced Case was deleted, made private, or turned into a draft after it was stored) renders as {id, available:false}; this read-time drift is the only place an "unavailable" reference can appear, since writes are gated by verifyCaseRefsExist. A repository lookup failure is propagated, never swallowed.
func (*CaseUseCase) ReopenCase ¶
func (*CaseUseCase) ResolveCaseRefs ¶
func (uc *CaseUseCase) ResolveCaseRefs(ctx context.Context, workspaceID string, ids []int64) ([]model.CaseRef, error)
ResolveCaseRefs resolves the given Case IDs in workspaceID to their CaseRef summaries, dropping any ID that is missing, private, or a draft (the caller renders those as "unavailable"). Used to label existing case_ref values for display. A single batch lookup keeps it N+1-safe.
func (*CaseUseCase) SetEventPublisher ¶
func (uc *CaseUseCase) SetEventPublisher(p CaseEventPublisher)
SetEventPublisher wires the lifecycle event publisher. Called once at startup after the job dispatch UseCase has been constructed. nil is allowed (Job dispatch effectively disabled).
func (*CaseUseCase) SubmitDraft ¶
func (uc *CaseUseCase) SubmitDraft(ctx context.Context, workspaceID string, id int64, patch *CaseUpdate) (*model.Case, error)
SubmitDraft promotes a draft case to OPEN and triggers the same activation side effects (Slack channel, invites, welcome, etc.) as a fresh CreateCase. The optional `patch` carries last-minute edits the caller wants to apply atomically before the promotion — passing them to this single usecase method (rather than separate UpdateCase + SubmitDraft calls from the controller) keeps the "save final edits and submit" business operation atomic: required-field validation, channel creation, and invites all see the same set of values, and a failure path leaves the draft consistent.
If activation fails the draft is kept in DRAFT so the user can retry without losing the saved entry.
func (*CaseUseCase) SyncCaseChannelUsers ¶
func (uc *CaseUseCase) SyncCaseChannelUsers(ctx context.Context, workspaceID string, caseID int64) (*model.Case, error)
SyncCaseChannelUsers synchronizes channel members from Slack API to the case
func (*CaseUseCase) UnassignCase ¶
func (uc *CaseUseCase) UnassignCase(ctx context.Context, workspaceID string, id int64, userIDs []string) (*model.Case, error)
UnassignCase atomically removes the given Slack user IDs from the case's assignee set. IDs not currently assigned are ignored. Removal needs no user existence check (a since-deleted user must still be removable). An empty userIDs slice is a no-op that returns the case unchanged.
func (*CaseUseCase) UpdateAgentSettings ¶
func (uc *CaseUseCase) UpdateAgentSettings(ctx context.Context, workspaceID string, caseID int64, additionalPrompt string, enabledSourceIDs []model.SourceID) (*model.Case, error)
UpdateAgentSettings replaces the Case-specific agent additional prompt and the AgentSourceIDs whitelist. enabledSourceIDs == nil or empty resets the selection to "use every Source". Non-empty IDs are validated against the Workspace's Source list — any unknown ID makes the whole update fail with ErrInvalidArgument (we never silently drop an ID the caller meant to keep). Order is preserved exactly as supplied so the UI selection round-trips unchanged.
func (*CaseUseCase) UpdateCase ¶
func (uc *CaseUseCase) UpdateCase(ctx context.Context, workspaceID string, id int64, patch CaseUpdate) (*model.Case, error)
func (*CaseUseCase) UpdateCaseStatus ¶
func (uc *CaseUseCase) UpdateCaseStatus(ctx context.Context, workspaceID string, id int64, boardStatus string) (*model.Case, error)
UpdateCaseStatus sets the configurable board status of a thread-mode Case and synchronises the lifecycle Status (a closed board status closes the case). It is the single entry point for both the Kanban drag-and-drop and the agent's `close` decision; CaseLifecycleClosed is published only on the open→closed edge so Jobs fire once.
type CreateGitHubSourceInput ¶
type CreateGitHubSourceInput struct {
Name string
Description string
Repositories []string // "owner/repo" or GitHub URL format
Enabled bool
}
CreateGitHubSourceInput represents input for creating a GitHub source
type CreateKnowledgeInput ¶
CreateKnowledgeInput is the domain-level input for creating a knowledge entry.
func (CreateKnowledgeInput) Validate ¶
func (input CreateKnowledgeInput) Validate() error
Validate enforces input invariants at the entry point: a title and at least one tag id are required, and the claim must be within the length limit. Tag existence is verified separately against the repository in CreateKnowledge.
type CreateMemoInput ¶
type CreateMemoInput struct {
CaseID int64
Title string
FieldValues map[string]model.FieldValue
}
CreateMemoInput is the unified input for MemoUseCase.CreateMemo.
type CreateNotionDBSourceInput ¶
type CreateNotionDBSourceInput struct {
Name string
Description string
DatabaseID string
Enabled bool
}
CreateNotionDBSourceInput represents input for creating a Notion DB source
type CreateNotionPageSourceInput ¶
type CreateNotionPageSourceInput struct {
Name string
Description string
PageID string
Enabled bool
Recursive bool
MaxDepth int
}
CreateNotionPageSourceInput represents input for creating a Notion Page source
type CreateSlackSourceInput ¶
type CreateSlackSourceInput struct {
Name string
Description string
ChannelIDs []string
Enabled bool
}
CreateSlackSourceInput represents input for creating a Slack source
type DashboardUseCase ¶
type DashboardUseCase struct {
// contains filtered or unexported fields
}
DashboardUseCase serves the login home dashboard: cross-workspace aggregation of the caller's own open Cases and incomplete Actions, favorite-workspace preferences, and the LLM-generated greeting. It is a dedicated usecase because it spans Case, Action, and UserPreference/HomeMessage repositories plus the workspace registry.
func (*DashboardUseCase) GenerateHomeMessage ¶
func (uc *DashboardUseCase) GenerateHomeMessage(ctx context.Context, clientTime time.Time, lang string) (string, error)
GenerateHomeMessage returns the home greeting for the caller, reusing the most recent stored message when it is still fresh (same language, within the window) and generating+appending a new one otherwise. Returns "" (no error) when no greeting LLM is configured.
func (*DashboardUseCase) GetFavoriteWorkspaces ¶
func (uc *DashboardUseCase) GetFavoriteWorkspaces(ctx context.Context) ([]string, error)
GetFavoriteWorkspaces returns the caller's favorite workspace IDs, filtered to those that still exist in the registry.
func (*DashboardUseCase) ListMyDueActions ¶
func (uc *DashboardUseCase) ListMyDueActions(ctx context.Context) ([]*model.MyDueAction, error)
ListMyDueActions returns, across every workspace, the caller's incomplete Actions on accessible open Cases, ordered by due date (overdue first, no due date last).
func (*DashboardUseCase) ListMyOpenCases ¶
func (uc *DashboardUseCase) ListMyOpenCases(ctx context.Context) ([]*model.MyOpenCase, error)
ListMyOpenCases returns, across every workspace, the open Cases the caller is assigned to and may access, newest activity / stalled first.
func (*DashboardUseCase) SetFavoriteWorkspaces ¶
func (uc *DashboardUseCase) SetFavoriteWorkspaces(ctx context.Context, workspaceIDs []string) ([]string, error)
SetFavoriteWorkspaces replaces the caller's favorite workspace list wholesale. Unknown workspace IDs are rejected; duplicates are removed (order preserved). Returns the stored list.
type DeleteActionStepInput ¶
type DeleteActionStepInput struct {
WorkspaceID string
ActionID int64
StepID string
Actor ActorRef
}
DeleteActionStepInput is the input for ActionStepUseCase.Delete.
type GitHubRepoValidationResult ¶
type GitHubRepoValidationResult struct {
Valid bool
Owner string
Repo string
FullName string
Description string
IsPrivate bool
PullRequestCount int
IssueCount int
CanFetchPullRequests bool
CanFetchIssues bool
ErrorMessage string
}
GitHubRepoValidationResult represents the result of GitHub repository validation
type ImportUseCase ¶
type ImportUseCase struct {
// contains filtered or unexported fields
}
ImportUseCase owns the "YAML → Case/Action" wizard. It delegates the actual Case / Action creation to the existing CaseUseCase / ActionUseCase so business rules (history events, private-case invariants, Slack-suppression because the Case is in DRAFT, etc.) stay in one place.
func NewImportUseCase ¶
func NewImportUseCase(repo interfaces.Repository, registry *model.WorkspaceRegistry, caseUC *CaseUseCase, actionUC *ActionUseCase) *ImportUseCase
NewImportUseCase constructs an ImportUseCase.
func (*ImportUseCase) Create ¶
func (uc *ImportUseCase) Create(ctx context.Context, workspaceID, content, originalFileName string) (*model.ImportSession, error)
Create parses, validates, and persists a new ImportSession in pending state. Caller must be authenticated; CreatorUserID is captured from the auth context.
func (*ImportUseCase) Execute ¶
func (uc *ImportUseCase) Execute(ctx context.Context, workspaceID string, id model.ImportSessionID) (*model.ImportSession, error)
Execute runs the persisted snapshot against the workspace, creating Case (DRAFT) and Action records via the existing usecases. The first failure halts the loop; subsequent items become skipped. No rollback is performed (DRAFTs are harmless to leave around — they have no Slack side effects).
func (*ImportUseCase) Get ¶
func (uc *ImportUseCase) Get(ctx context.Context, workspaceID string, id model.ImportSessionID) (*model.ImportSession, error)
Get returns the session if it exists AND the caller is the creator. Returns ErrImportSessionNotFound otherwise so callers cannot probe other users' session IDs.
type JobRunLogPage ¶
JobRunLogPage is the result of ListLogsByCase. NextCursor is non-nil only when more pages exist; the value is an opaque base64 token that the caller passes back as `after` on the next call.
type JobRunUseCase ¶
type JobRunUseCase struct {
// contains filtered or unexported fields
}
JobRunUseCase exposes read-only access to Job execution history and the per-Run timeline. It is intentionally narrow: the CaseAgent page and the JobRunLog detail page both rely on these three methods (plus CaseUseCase for the parent-Case access check, which is reused here).
Access control follows the same Private Case pattern as CaseUseCase: the parent Case is loaded first; if the caller does not belong to its channel, the read is refused with ErrAccessDenied. System contexts without an auth token (background runner, etc.) bypass the check — the same backward-compatibility carveout already used elsewhere.
func NewJobRunUseCase ¶
func NewJobRunUseCase(repo interfaces.Repository, registry *model.WorkspaceRegistry) *JobRunUseCase
NewJobRunUseCase wires the JobRunUseCase. registry may be nil: the jobName field on returned logs falls back to the JobID when no entry is registered (e.g. early bootstrap), and never blocks the call.
func (*JobRunUseCase) GetLog ¶
func (uc *JobRunUseCase) GetLog(ctx context.Context, workspaceID string, caseID int64, runID string) (*model.JobRunLog, error)
GetLog returns a single JobRunLog by RunID. The runID is unique per Run, but the storage layout includes the JobID in the document path, so we resolve the JobID by walking the per-Case JobRun list (small) and probing each one. This avoids a collectionGroup query.
func (*JobRunUseCase) ListCaseJobs ¶
func (uc *JobRunUseCase) ListCaseJobs(ctx context.Context, workspaceID string, caseID int64) ([]*model.Job, error)
ListCaseJobs returns the enabled Job definitions that can fire against the given Case. Definitions come from the in-memory Workspace registry (workspace TOML), never a repository. A scheduled Job is included only while the Case is OPEN — mirroring the ScheduledScanner, which skips DRAFT/CLOSED cases — whereas a case-lifecycle Job is always included.
Access control matches the other JobRun reads: the parent Case is loaded first and a non-member caller is refused with ErrAccessDenied; system contexts without an auth token bypass the check. When the registry is unset (early bootstrap) the result is an empty slice.
func (*JobRunUseCase) ListEvents ¶
func (uc *JobRunUseCase) ListEvents(ctx context.Context, workspaceID string, caseID int64, runID string) ([]*model.JobRunEvent, error)
ListEvents returns every JobRunEvent under (workspace, case, run) in ascending Sequence order. As with GetLog, the JobID is resolved by walking the per-Case JobRun list first.
func (*JobRunUseCase) ListLogsByCase ¶
func (uc *JobRunUseCase) ListLogsByCase(ctx context.Context, workspaceID string, caseID int64, page int, after *string) (*JobRunLogPage, error)
ListLogsByCase returns one page of JobRunLogs for the given Case across every Job that has ever run against it, ordered newest-first.
Pagination semantics: page is the requested size (clamped to [1, JobRunLogPageMaxSize], defaulting to JobRunLogPageDefaultSize on zero/negative). `after` is the opaque cursor from a previous call; nil/empty means "start at the head".
Implementation note: the storage layout is per-Job (logs live under jobRuns/{job}/logs/), so a true cross-job query would need a Firestore collectionGroup (and a composite index). To stay within the project's "no new indexes" rule we fan out to one List per Job in parallel (small N: handful of Jobs per Case) and merge in memory. The cursor is then applied to the merged slice.
func (*JobRunUseCase) ResolveJobName ¶
func (uc *JobRunUseCase) ResolveJobName(ctx context.Context, workspaceID, jobID, eventType string) string
ResolveJobName returns the human-readable Job name from the workspace TOML registry, falling back to the raw JobID when no entry exists. Exposed so resolvers can label runs without re-loading the registry themselves. A mention-triggered run (eventType == EventTypeMention) is not a configured Job — its JobID is an opaque per-turn id — so it resolves to a localized "Mention" label instead.
type KnowledgeUseCase ¶
type KnowledgeUseCase struct {
// contains filtered or unexported fields
}
KnowledgeUseCase orchestrates workspace-wide shared knowledge operations. Embedding is optional: when no embed client is configured the use case degrades gracefully (no semantic vectors, substring search fallback).
func NewKnowledgeUseCase ¶
func NewKnowledgeUseCase(repo interfaces.Repository, embedClient interfaces.EmbedClient) *KnowledgeUseCase
NewKnowledgeUseCase constructs a KnowledgeUseCase. embedClient may be nil (fail-open: create/update still succeed and search falls back to substring).
func (*KnowledgeUseCase) CreateKnowledge ¶
func (uc *KnowledgeUseCase) CreateKnowledge(ctx context.Context, workspaceID string, input CreateKnowledgeInput) (*model.Knowledge, error)
CreateKnowledge creates a new knowledge entry. The embedding is generated best-effort: a failure or a missing embed client never blocks creation.
func (*KnowledgeUseCase) DeleteKnowledge ¶
func (uc *KnowledgeUseCase) DeleteKnowledge(ctx context.Context, workspaceID string, id model.KnowledgeID) error
DeleteKnowledge removes a knowledge entry.
func (*KnowledgeUseCase) GetKnowledge ¶
func (uc *KnowledgeUseCase) GetKnowledge(ctx context.Context, workspaceID string, id model.KnowledgeID) (*model.Knowledge, error)
GetKnowledge retrieves a knowledge entry by ID.
func (*KnowledgeUseCase) ListKnowledge ¶
func (uc *KnowledgeUseCase) ListKnowledge(ctx context.Context, workspaceID string, opts interfaces.KnowledgeListOptions) ([]*model.Knowledge, error)
ListKnowledge lists knowledge entries with an optional tag AND filter.
func (*KnowledgeUseCase) SearchKnowledge ¶
func (uc *KnowledgeUseCase) SearchKnowledge(ctx context.Context, workspaceID string, input SearchKnowledgeInput) ([]*model.Knowledge, error)
SearchKnowledge ranks entries by semantic similarity to the query. When no embedding is available (no embed client, embedding failure, or candidates without vectors) it falls back to a substring-match score over title + claim.
func (*KnowledgeUseCase) UpdateKnowledge ¶
func (uc *KnowledgeUseCase) UpdateKnowledge(ctx context.Context, workspaceID string, input UpdateKnowledgeInput) (*model.Knowledge, error)
UpdateKnowledge applies a partial update. The embedding is regenerated when the title or claim changes (best-effort).
type MemoConfiguration ¶
type MemoConfiguration struct {
Enabled bool
Description string
Fields []config.FieldDefinition
}
MemoConfiguration describes a workspace's memo configuration for the WebUI: the strong definition and the custom field definitions used to render the memo form. Both are empty when the workspace has not enabled memos.
type MemoUseCase ¶
type MemoUseCase struct {
// contains filtered or unexported fields
}
MemoUseCase orchestrates Case-scoped memo operations. Every write funnels through the same field validation + access control gate so the GraphQL/WebUI path and the agent-tool path enforce identical rules.
func NewMemoUseCase ¶
func NewMemoUseCase(repo interfaces.Repository, registry *model.WorkspaceRegistry) *MemoUseCase
NewMemoUseCase constructs a MemoUseCase.
func (*MemoUseCase) ArchiveMemo ¶
func (uc *MemoUseCase) ArchiveMemo(ctx context.Context, workspaceID string, caseID int64, id model.MemoID) (*model.Memo, error)
ArchiveMemo soft-deletes a memo by setting ArchivedAt. Idempotent: archiving an already-archived memo is a no-op write that returns the current state.
func (*MemoUseCase) CreateMemo ¶
func (uc *MemoUseCase) CreateMemo(ctx context.Context, workspaceID string, in CreateMemoInput) (*model.Memo, error)
CreateMemo validates and persists a new memo within a Case. Field values are fully validated (required fields enforced, unknown field ids rejected).
func (*MemoUseCase) GetMemo ¶
func (uc *MemoUseCase) GetMemo(ctx context.Context, workspaceID string, caseID int64, id model.MemoID) (*model.Memo, error)
GetMemo loads a single memo within a Case. Returns ErrAccessDenied for a private case the (token-bearing) caller cannot access.
func (*MemoUseCase) ListMemosByCase ¶
func (uc *MemoUseCase) ListMemosByCase(ctx context.Context, workspaceID string, caseID int64, scope interfaces.MemoArchiveScope) ([]*model.Memo, error)
ListMemosByCase returns the memos of a Case filtered by scope. For a private case the (token-bearing) caller cannot access, it returns an empty slice rather than an error so list surfaces degrade quietly (read-side restriction).
func (*MemoUseCase) MemoConfiguration ¶
func (uc *MemoUseCase) MemoConfiguration(workspaceID string) (*MemoConfiguration, error)
MemoConfiguration returns the workspace memo configuration for the WebUI. When the workspace has no memo schema it returns a disabled configuration (Enabled=false, empty fields) rather than an error, so the frontend can hide the Memos tab.
func (*MemoUseCase) UnarchiveMemo ¶
func (uc *MemoUseCase) UnarchiveMemo(ctx context.Context, workspaceID string, caseID int64, id model.MemoID) (*model.Memo, error)
UnarchiveMemo restores a soft-deleted memo by clearing ArchivedAt.
func (*MemoUseCase) UpdateMemo ¶
func (uc *MemoUseCase) UpdateMemo(ctx context.Context, workspaceID string, in UpdateMemoInput) (*model.Memo, error)
UpdateMemo applies a partial patch to an existing memo. The patch field values are merged over the stored values and the merged set is validated in full.
type MentionProposalUseCase ¶
type MentionProposalUseCase struct {
// contains filtered or unexported fields
}
MentionProposalUseCase handles app_mention events that occur in channels NOT bound to an existing Case. It funnels each mention into proposal.UseCase (the open-mode planner / sub-agent runtime), passing a per-mention slackDraftHandler that translates terminal actions and trace updates into Slack messages.
func NewMentionProposalUseCase ¶
func NewMentionProposalUseCase( repo interfaces.Repository, registry *model.WorkspaceRegistry, slackService slacksvc.Service, draftUC *proposal.UseCase, ) *MentionProposalUseCase
NewMentionProposalUseCase constructs a MentionProposalUseCase. All dependencies are mandatory; callers that cannot supply a Slack service should refrain from constructing this usecase (and the Slack interaction handler that depends on it) entirely.
func (*MentionProposalUseCase) HandleAppMention ¶
func (uc *MentionProposalUseCase) HandleAppMention(ctx context.Context, ev *slackevents.AppMentionEvent) error
HandleAppMention runs the initial-mention flow: candidate workspace resolution → message collection → draft persistence → planner-driven turn (proposal.UseCase.RunTurn). The slackDraftHandler renders the planner's terminal action (post_message / post_question / materialize) into Slack.
It is the caller's responsibility to ensure the channel is NOT bound to an existing Case (the dispatch in SlackUseCases handles that branch).
func (*MentionProposalUseCase) HandleCancel ¶
func (uc *MentionProposalUseCase) HandleCancel(ctx context.Context, callback *goslack.InteractionCallback, _ *goslack.BlockAction) error
HandleCancel marks the draft preview as canceled in place: the existing blocks are kept (so the conversation has a record of what was drafted), every ActionBlock is stripped (workspace selector + buttons live in the same ActionBlock now, both go), and a "Canceled" tail is appended. The underlying draft is deleted from the repository.
func (*MentionProposalUseCase) HandleEdit ¶
func (uc *MentionProposalUseCase) HandleEdit(ctx context.Context, callback *goslack.InteractionCallback, action *goslack.BlockAction) error
HandleEdit opens the dynamic Edit modal for the currently-selected workspace.
func (*MentionProposalUseCase) HandleEditSubmit ¶
func (uc *MentionProposalUseCase) HandleEditSubmit(ctx context.Context, caseUC *CaseUseCase, callback *goslack.InteractionCallback) error
HandleEditSubmit processes the view_submission for the Edit modal.
func (*MentionProposalUseCase) HandleQuestionSubmit ¶
func (uc *MentionProposalUseCase) HandleQuestionSubmit(ctx context.Context, callback *goslack.InteractionCallback, action *goslack.BlockAction) error
HandleQuestionSubmit is the Submit-button entry point for the open-mode question form. It loads the live session, parses the user's selections against the pending question snapshot, validates that every item has an answer, swaps the form message into a read-only "answered" record, and resumes the planner with the formatted answers as the next-turn user input. Validation failures re-render the form with an inline error so the user can fix and resubmit.
func (*MentionProposalUseCase) HandleSelectWorkspace ¶
func (uc *MentionProposalUseCase) HandleSelectWorkspace(ctx context.Context, callback *goslack.InteractionCallback, action *goslack.BlockAction) error
HandleSelectWorkspace runs when the user changes the workspace selector on the preview ephemeral. It re-routes the request through proposal.UseCase.RunTurn with a TriggerWSSwitch trigger; the planner re-materialises against the new workspace's schema using the existing conversation history. The lock-first ordering of F4-3 is preserved by setting InferenceInProgress before the turn starts so concurrent interactions (Submit/Edit/Cancel) refuse.
func (*MentionProposalUseCase) HandleSubmit ¶
func (uc *MentionProposalUseCase) HandleSubmit(ctx context.Context, caseUC *CaseUseCase, callback *goslack.InteractionCallback, action *goslack.BlockAction) error
HandleSubmit creates the Case using the current materialization and posts the completion notification.
func (*MentionProposalUseCase) HandleThreadReply ¶
func (uc *MentionProposalUseCase) HandleThreadReply(ctx context.Context, ev *slackevents.MessageEvent) error
HandleThreadReply runs when the dispatcher's F1-F8 filter chain has decided that a non-mention thread reply should resume the open-mode draft turn. The Session's LastAction is post_question — the planner will read the new user input from history and produce the next action.
type NoAuthnUseCase ¶
type NoAuthnUseCase struct {
// contains filtered or unexported fields
}
NoAuthnUseCase provides authentication using a specified user (for development/testing)
func NewNoAuthnUseCase ¶
func NewNoAuthnUseCase(repo interfaces.Repository, sub, email, name string) *NoAuthnUseCase
NewNoAuthnUseCase creates a new NoAuthnUseCase instance with specified user info
func (*NoAuthnUseCase) GetAuthURL ¶
func (uc *NoAuthnUseCase) GetAuthURL(state string) string
GetAuthURL returns a dummy URL (should not be called in no-auth mode)
func (*NoAuthnUseCase) HandleCallback ¶
HandleCallback handles OAuth callback (should not be called in no-auth mode)
func (*NoAuthnUseCase) IsNoAuthn ¶
func (uc *NoAuthnUseCase) IsNoAuthn() bool
IsNoAuthn returns true for NoAuthnUseCase
func (*NoAuthnUseCase) ValidateToken ¶
func (uc *NoAuthnUseCase) ValidateToken(ctx context.Context, tokenID auth.TokenID, tokenSecret auth.TokenSecret) (*auth.Token, error)
ValidateToken always returns a token for the specified user
type NotionDBValidationResult ¶
type NotionDBValidationResult struct {
Valid bool
DatabaseTitle string
DatabaseURL string
ErrorMessage string
}
NotionDBValidationResult represents the result of Notion database validation
type NotionPageValidationResult ¶
type NotionPageValidationResult struct {
Valid bool
PageTitle string
PageURL string
ErrorMessage string
}
NotionPageValidationResult represents the result of Notion page validation
type OpenIDConfiguration ¶
type OpenIDConfiguration struct {
Issuer string `json:"issuer"`
AuthorizationEndpoint string `json:"authorization_endpoint"`
TokenEndpoint string `json:"token_endpoint"`
UserinfoEndpoint string `json:"userinfo_endpoint"`
JWKSURI string `json:"jwks_uri"`
ScopesSupported []string `json:"scopes_supported"`
ResponseTypesSupported []string `json:"response_types_supported"`
ResponseModesSupported []string `json:"response_modes_supported"`
GrantTypesSupported []string `json:"grant_types_supported"`
SubjectTypesSupported []string `json:"subject_types_supported"`
IDTokenSigningAlgValuesSupported []string `json:"id_token_signing_alg_values_supported"`
ClaimsSupported []string `json:"claims_supported"`
ClaimsParameterSupported bool `json:"claims_parameter_supported"`
RequestParameterSupported bool `json:"request_parameter_supported"`
RequestURIParameterSupported bool `json:"request_uri_parameter_supported"`
TokenEndpointAuthMethodsSupported []string `json:"token_endpoint_auth_methods_supported"`
}
OpenIDConfiguration represents Slack's OpenID Connect configuration
type Option ¶
type Option func(*UseCases)
func WithAuth ¶
func WithAuth(auth AuthUseCaseInterface) Option
func WithBaseURL ¶
func WithDashboardStaleThreshold ¶
WithDashboardStaleThreshold sets the age after which an open Case with no update is flagged as stalled on the home dashboard. A non-positive value disables stale detection (Stalled is always false).
func WithEmbedClient ¶
func WithEmbedClient(client interfaces.EmbedClient) Option
WithEmbedClient sets the embedding client. The Memory / Knowledge similarity search consumers were demolished pending redesign, so the client currently has no production reader; the option is preserved so the upcoming redesign can drop similarity-search features back in without rewiring the CLI / usecase boundary. Configured separately from the chat completion LLM so it can target Gemini regardless of provider.
func WithGitHubService ¶
func WithHistoryRepository ¶
func WithHistoryRepository(repo gollem.HistoryRepository) Option
WithHistoryRepository sets the gollem.HistoryRepository used by the agent session flow to persist conversation history across mentions.
func WithHomeMessageLLMClient ¶
WithHomeMessageLLMClient sets a dedicated LLM client for the home greeting. When omitted, the shared chat LLM client (WithLLMClient) is used if present; when neither is set, the greeting is disabled (GenerateHomeMessage returns "").
func WithJiraTools ¶
WithJiraTools configures the already-expanded Jira read tools (see pkg/agent/tool/jira). Unlike WithGitHubService this takes a plain tool slice, not a client: gollem exposes no exported helper to turn a gollem.ToolSet into []gollem.Tool, so the caller (pkg/cli/config.Jira. Configure) expands it once at startup before passing it in here.
func WithLLMClient ¶
func WithNotificationSlotDuration ¶
WithNotificationSlotDuration sets the rolling window length used to aggregate Slack channel-side change notifications into a single editable message. Pass 0 (the default) to disable aggregation, restoring the legacy per-event reply_broadcast path.
func WithNotion ¶
func WithNotionToolClient ¶
func WithNotionToolClient(c notiontool.Client) Option
WithNotionToolClient configures the agent-tool Notion client. When set, the agent gains the notion__search and notion__get_page tools.
func WithSlackAdminService ¶
func WithSlackAdminService(svc slack.AdminService) Option
func WithSlackMessageRetriever ¶
func WithSlackMessageRetriever(svc slacktool.MessageRetriever) Option
WithSlackMessageRetriever configures the Slack User-token-backed message retriever used by slack__get_messages. When set, conversations.replies / conversations.history are called with the User token, which allows reading public channels without bot membership. Requires the underlying User OAuth Token to have the channels:history scope. nil keeps the existing Bot-token path (which returns not_in_channel when the bot is not a channel member).
func WithSlackSearchService ¶
func WithSlackSearchService(svc slacktool.SearchService) Option
WithSlackSearchService configures the Slack User-token-backed search client. When set, the agent gains the slack__search_messages tool. Requires the underlying User OAuth Token to have the search:read scope.
func WithSlackService ¶
func WithTraceRepository ¶
func WithTraceRepository(repo trace.Repository) Option
WithTraceRepository sets the trace.Repository used by the agent session flow to persist execution traces.
func WithWebFetch ¶
func WithWebFetch(cfg webfetch.ClientConfig) Option
WithWebFetch configures the agent webfetch tool's HTTP-side settings. The shared LLM client (used for injection screening) is injected in New, so the tool is built only when both these settings and an LLM client are present.
func WithWorkspaceGroups ¶
func WithWorkspaceGroups(r *model.WorkspaceGroupRegistry) Option
WithWorkspaceGroups configures the deployment-wide workspace group registry (loaded from --global-config). Optional: when omitted, New defaults to an empty registry so WorkspaceGroups() never returns nil.
type RenameActionStepInput ¶
type RenameActionStepInput struct {
WorkspaceID string
ActionID int64
StepID string
Title string
Actor ActorRef
}
RenameActionStepInput is the input for ActionStepUseCase.Rename.
type SearchKnowledgeInput ¶
type SearchKnowledgeInput struct {
// Query is the natural-language search text. Empty returns the (optionally
// tag-filtered) list ordered by CreatedAt.
Query string
// TagIDs applies an AND pre-filter before ranking.
TagIDs []model.TagID
// Limit caps the number of returned entries. Zero or negative means no cap;
// the caller (resolver / tool) supplies the default.
Limit int
}
SearchKnowledgeInput controls a semantic search query.
type SetActionStepDoneInput ¶
type SetActionStepDoneInput struct {
WorkspaceID string
ActionID int64
StepID string
Done bool
Actor ActorRef
}
SetActionStepDoneInput is the input for ActionStepUseCase.SetDone.
type SlackChannelInfo ¶
SlackChannelInfo represents channel information returned from the API
type SlackIDToken ¶
type SlackIDToken struct {
Sub string `json:"sub"`
Email string `json:"email"`
Name string `json:"name"`
}
SlackIDToken represents the decoded ID token from Slack
type SlackSyncMode ¶
type SlackSyncMode int
SlackSyncMode controls how UpdateAction interacts with Slack.
const ( // SlackSyncFull updates the existing Slack message and posts a thread // notification for visible field changes (default). SlackSyncFull SlackSyncMode = iota // SlackSyncMessageOnly only refreshes the existing Slack message; no // thread notification is posted. SlackSyncMessageOnly // SlackSyncSkip leaves Slack untouched. SlackSyncSkip )
type SlackTokenResponse ¶
type SlackTokenResponse struct {
OK bool `json:"ok"`
AccessToken string `json:"access_token"`
TokenType string `json:"token_type"`
Scope string `json:"scope"`
BotUserID string `json:"bot_user_id"`
AppID string `json:"app_id"`
Team struct {
Name string `json:"name"`
ID string `json:"id"`
} `json:"team"`
Enterprise interface{} `json:"enterprise"`
AuthedUser struct {
ID string `json:"id"`
Scope string `json:"scope"`
AccessToken string `json:"access_token"`
TokenType string `json:"token_type"`
} `json:"authed_user"`
IDToken string `json:"id_token"`
Error string `json:"error"`
}
SlackTokenResponse represents the response from Slack token exchange
type SlackUseCases ¶
type SlackUseCases struct {
// contains filtered or unexported fields
}
SlackUseCases handles Slack-related business logic
func NewSlackUseCases ¶
func NewSlackUseCases(repo interfaces.Repository, registry *model.WorkspaceRegistry, agent *AgentUseCase, mentionProposal *MentionProposalUseCase, slackService slacksvc.Service) *SlackUseCases
NewSlackUseCases creates a new SlackUseCases instance. agent and mentionProposal are mandatory — Slack mention dispatch requires both.
func (*SlackUseCases) CleanupOldMessages ¶
CleanupOldMessages deletes messages older than the specified time
func (*SlackUseCases) HandleActionCreationSubmit ¶
func (uc *SlackUseCases) HandleActionCreationSubmit(ctx context.Context, actionUC *ActionUseCase, callback *slack.InteractionCallback) error
HandleActionCreationSubmit processes the action creation modal submission. All side-effects (Slack notification post, ActionEvent record, etc.) live inside ActionUseCase.CreateAction; this handler only translates the view state into the unified usecase input.
func (*SlackUseCases) HandleCaseCreationSubmit ¶
func (uc *SlackUseCases) HandleCaseCreationSubmit(ctx context.Context, caseUC *CaseUseCase, callback *slack.InteractionCallback) error
HandleCaseCreationSubmit processes the case creation modal submission (view_submission path — i.e. the footer Submit button or Enter on an input). The Options checkbox group governs two flags: "private" gates channel-member-only access; "draft" diverts the request to CaseUseCase.CreateDraft so the entry is persisted in status=DRAFT without creating a Slack channel until the user later submits the draft from the web UI.
func (*SlackUseCases) HandleCaseEditSubmit ¶
func (uc *SlackUseCases) HandleCaseEditSubmit(ctx context.Context, caseUC *CaseUseCase, callback *slack.InteractionCallback) error
HandleCaseEditSubmit processes the case edit modal submission. It updates the case using CaseUseCase and posts a confirmation message.
func (*SlackUseCases) HandleCommandChoiceSubmit ¶
func (uc *SlackUseCases) HandleCommandChoiceSubmit(ctx context.Context, callback *slack.InteractionCallback) (*slack.ModalViewRequest, error)
HandleCommandChoiceSubmit processes the choice modal submission. It returns the next view (case edit modal or action creation modal) so the controller can respond with response_action: update.
func (*SlackUseCases) HandleSaveAsDraftClick ¶
func (uc *SlackUseCases) HandleSaveAsDraftClick(ctx context.Context, caseUC *CaseUseCase, callback *slack.InteractionCallback) error
HandleSaveAsDraftClick handles the "Save as Draft" button click that originates from the Case creation modal. The block_actions interaction carries the in-flight view state (title, description, custom fields, privacy flag) plus the modal's private_metadata (workspace ID, channel, source team). We translate that state into a CreateDraft call so the half-written entry is persisted in CaseStatus.DRAFT — the user can later return to it from the Web Drafts page and Submit (promoting to OPEN) or Discard (delete).
This entry point is invoked from the async tail of the block_actions dispatcher; the controller already returned 200 to Slack. We post an ephemeral receipt to the channel and replace the modal with a small "Saved" splash so the user has feedback without us racing the trigger_id TTL.
func (*SlackUseCases) HandleSlackEvent ¶
func (uc *SlackUseCases) HandleSlackEvent(ctx context.Context, event *slackevents.EventsAPIEvent) error
HandleSlackEvent processes Slack Events API events
func (*SlackUseCases) HandleSlackMessage ¶
HandleSlackMessage saves a Slack message
func (*SlackUseCases) HandleSlashCommand ¶
func (uc *SlackUseCases) HandleSlashCommand(ctx context.Context, triggerID, userID, channelID, workspaceID, sourceTeamID, text string) error
HandleSlashCommand handles a Slack slash command.
In a channel linked to an existing case, the optional `text` subcommand chooses what to do:
- "update" → open the case edit modal
- "action" → open the action creation modal
- empty → open a small choice modal that funnels into one of the above
- anything else → ephemeral error
In a channel without a linked case, the subcommand is ignored and the existing case-creation flow runs.
func (*SlackUseCases) HandleWorkspaceSelectSubmit ¶
func (uc *SlackUseCases) HandleWorkspaceSelectSubmit(ctx context.Context, callback *slack.InteractionCallback) (*slack.ModalViewRequest, error)
HandleWorkspaceSelectSubmit processes the workspace selection modal submission. It returns the case creation modal view to replace the current modal via response_action: update.
type SourceUseCase ¶
type SourceUseCase struct {
// contains filtered or unexported fields
}
SourceUseCase handles source-related business logic
func NewSourceUseCase ¶
func NewSourceUseCase(repo interfaces.Repository, notionService notion.Service, slackService slack.Service, githubService githubAPI) *SourceUseCase
NewSourceUseCase creates a new SourceUseCase instance
func (*SourceUseCase) CreateGitHubSource ¶
func (uc *SourceUseCase) CreateGitHubSource(ctx context.Context, workspaceID string, input CreateGitHubSourceInput) (*model.Source, error)
CreateGitHubSource creates a new GitHub source
func (*SourceUseCase) CreateNotionDBSource ¶
func (uc *SourceUseCase) CreateNotionDBSource(ctx context.Context, workspaceID string, input CreateNotionDBSourceInput) (*model.Source, error)
CreateNotionDBSource creates a new Notion DB source with validation
func (*SourceUseCase) CreateNotionPageSource ¶
func (uc *SourceUseCase) CreateNotionPageSource(ctx context.Context, workspaceID string, input CreateNotionPageSourceInput) (*model.Source, error)
CreateNotionPageSource creates a new Notion Page source with validation
func (*SourceUseCase) CreateSlackSource ¶
func (uc *SourceUseCase) CreateSlackSource(ctx context.Context, workspaceID string, input CreateSlackSourceInput) (*model.Source, error)
CreateSlackSource creates a new Slack source
func (*SourceUseCase) DeleteSource ¶
func (uc *SourceUseCase) DeleteSource(ctx context.Context, workspaceID string, id model.SourceID) error
DeleteSource removes a source
func (*SourceUseCase) GetSlackChannelNames ¶
func (uc *SourceUseCase) GetSlackChannelNames(ctx context.Context, ids []string) (map[string]string, error)
GetSlackChannelNames retrieves channel names for given IDs
func (*SourceUseCase) GetSource ¶
func (uc *SourceUseCase) GetSource(ctx context.Context, workspaceID string, id model.SourceID) (*model.Source, error)
GetSource retrieves a source by ID
func (*SourceUseCase) ListSlackChannels ¶
func (uc *SourceUseCase) ListSlackChannels(ctx context.Context) ([]SlackChannelInfo, error)
ListSlackChannels lists available Slack channels
func (*SourceUseCase) ListSources ¶
func (uc *SourceUseCase) ListSources(ctx context.Context, workspaceID string) ([]*model.Source, error)
ListSources retrieves all sources
func (*SourceUseCase) UpdateGitHubSource ¶
func (uc *SourceUseCase) UpdateGitHubSource(ctx context.Context, workspaceID string, input UpdateGitHubSourceInput) (*model.Source, error)
UpdateGitHubSource updates a GitHub source
func (*SourceUseCase) UpdateNotionDBSource ¶
func (uc *SourceUseCase) UpdateNotionDBSource(ctx context.Context, workspaceID string, input UpdateNotionDBSourceInput) (*model.Source, error)
UpdateNotionDBSource updates a Notion DB source.
func (*SourceUseCase) UpdateNotionPageSource ¶
func (uc *SourceUseCase) UpdateNotionPageSource(ctx context.Context, workspaceID string, input UpdateNotionPageSourceInput) (*model.Source, error)
UpdateNotionPageSource updates a Notion Page source.
func (*SourceUseCase) UpdateSlackSource ¶
func (uc *SourceUseCase) UpdateSlackSource(ctx context.Context, workspaceID string, input UpdateSlackSourceInput) (*model.Source, error)
UpdateSlackSource updates a Slack source
func (*SourceUseCase) UpdateSource ¶
func (uc *SourceUseCase) UpdateSource(ctx context.Context, workspaceID string, input UpdateSourceInput) (*model.Source, error)
UpdateSource updates source common fields
func (*SourceUseCase) ValidateGitHubRepo ¶
func (uc *SourceUseCase) ValidateGitHubRepo(ctx context.Context, repository string) (*GitHubRepoValidationResult, error)
ValidateGitHubRepo validates a GitHub repository and returns metadata
func (*SourceUseCase) ValidateNotionDB ¶
func (uc *SourceUseCase) ValidateNotionDB(ctx context.Context, databaseID string) (*NotionDBValidationResult, error)
ValidateNotionDB validates a Notion database ID (or URL) and returns metadata
func (*SourceUseCase) ValidateNotionPage ¶
func (uc *SourceUseCase) ValidateNotionPage(ctx context.Context, pageID string) (*NotionPageValidationResult, error)
ValidateNotionPage validates a Notion page ID (or URL) and returns metadata
type TagUseCase ¶
type TagUseCase struct {
// contains filtered or unexported fields
}
TagUseCase orchestrates workspace-wide Tag operations. Tags are first-class classification labels referenced by Knowledge entries via TagID.
func NewTagUseCase ¶
func NewTagUseCase(repo interfaces.Repository) *TagUseCase
NewTagUseCase constructs a TagUseCase.
func (*TagUseCase) CreateTag ¶
CreateTag creates a new tag. Name is optional and is trimmed; the ID is a freshly generated immutable TagID.
func (*TagUseCase) DeleteTag ¶
DeleteTag removes a tag, but only when no knowledge entry references it. A tag still in use is refused with ErrTagInUse so a delete can never strand a knowledge entry with a dangling tag id.
func (*TagUseCase) GetTag ¶
func (uc *TagUseCase) GetTag(ctx context.Context, workspaceID string, id model.TagID) (*model.Tag, error)
GetTag retrieves a tag by ID.
type UpdateActionInput ¶
type UpdateActionInput struct {
ID int64
CaseID *int64
Title *string
Description *string
AssigneeID *string // nil = no change; "" is not a valid clear, use ClearAssignee.
Status *types.ActionStatus
DueDate *time.Time
ClearDueDate bool
ClearAssignee bool
SlackMessageTS *string
SlackSync SlackSyncMode
Actor ActorRef
// RejectNonHumanAssignee, when true, drops AssigneeID changes whose
// target user is missing from the SlackUser DB. The DB only stores
// non-bot users, so this is a guard against picks coming from the
// Slack users_select element (which has no built-in bot filter).
// GraphQL/WebUI callers leave this false: their pickers already show
// only synced humans, and silently dropping the change would just
// look like a broken UI.
RejectNonHumanAssignee bool
}
UpdateActionInput is the unified input for ActionUseCase.UpdateAction.
type UpdateGitHubSourceInput ¶
type UpdateGitHubSourceInput struct {
ID model.SourceID
Name *string
Description *string
Repositories []string // "owner/repo" or GitHub URL format; nil means no change
Enabled *bool
}
UpdateGitHubSourceInput represents input for updating a GitHub source
type UpdateKnowledgeInput ¶
type UpdateKnowledgeInput struct {
ID model.KnowledgeID
Title *string
Claim *string
TagIDs *[]model.TagID
}
UpdateKnowledgeInput is the domain-level input for updating a knowledge entry. Title / Claim / TagIDs are pointers: nil means "leave unchanged".
func (UpdateKnowledgeInput) Validate ¶
func (input UpdateKnowledgeInput) Validate() error
Validate enforces input invariants for the fields that are present.
type UpdateMemoInput ¶
type UpdateMemoInput struct {
ID model.MemoID
CaseID int64
Title *string
FieldValues map[string]model.FieldValue
}
UpdateMemoInput is the unified input for MemoUseCase.UpdateMemo. Title is a pointer so an absent title means "no change". FieldValues is a patch merged over the existing values; the merged set is then validated in full.
type UpdateNotionDBSourceInput ¶
type UpdateNotionDBSourceInput struct {
ID model.SourceID
Name *string
Description *string
DatabaseID *string
Enabled *bool
}
UpdateNotionDBSourceInput represents input for updating a Notion DB source. DatabaseID is a pointer so that callers can distinguish "no change" (nil) from an explicit value. When DatabaseID is non-nil, the new value is re-validated against the Notion API and the cached title/URL are refreshed.
type UpdateNotionPageSourceInput ¶
type UpdateNotionPageSourceInput struct {
ID model.SourceID
Name *string
Description *string
PageID *string
Enabled *bool
Recursive *bool
MaxDepth *int
}
UpdateNotionPageSourceInput represents input for updating a Notion Page source. PageID is a pointer so that callers can distinguish "no change" (nil) from an explicit value. When PageID is non-nil the new value is re-validated against the Notion API and the cached title/URL are refreshed. Recursive and MaxDepth are updated independently of PageID changes.
type UpdateSlackSourceInput ¶
type UpdateSlackSourceInput struct {
ID model.SourceID
Name *string
Description *string
ChannelIDs []string
Enabled *bool
}
UpdateSlackSourceInput represents input for updating a Slack source
type UpdateSourceInput ¶
UpdateSourceInput represents input for updating a source
type UseCases ¶
type UseCases struct {
Case *CaseUseCase
Action *ActionUseCase
Memo *MemoUseCase
Knowledge *KnowledgeUseCase
Tag *TagUseCase
ActionStep *ActionStepUseCase
Agent *AgentUseCase
Auth AuthUseCaseInterface
Slack *SlackUseCases
Source *SourceUseCase
Assist *AssistUseCase
MentionProposal *MentionProposalUseCase
JobRun *JobRunUseCase
Import *ImportUseCase
Dashboard *DashboardUseCase
// contains filtered or unexported fields
}
func New ¶
func New(repo interfaces.Repository, registry *model.WorkspaceRegistry, opts ...Option) *UseCases
func (*UseCases) NotionToolClient ¶
func (uc *UseCases) NotionToolClient() notiontool.Client
NotionToolClient returns the agent-tool Notion client (nil when no Notion token was configured). Exposed so the Job runtime wiring can bind notion__search / notion__get_page into the Job tool set.
func (*UseCases) SlackMessageRetriever ¶
func (uc *UseCases) SlackMessageRetriever() slacktool.MessageRetriever
SlackMessageRetriever returns the Slack User-token-backed message retriever (nil when no User OAuth Token was configured). Exposed so the Job runtime wiring can let slack__get_messages read channels the bot has not joined.
func (*UseCases) SlackSearchService ¶
func (uc *UseCases) SlackSearchService() slacktool.SearchService
SlackSearchService returns the Slack User-token-backed search client (nil when no User OAuth Token was configured). Exposed so the Job runtime wiring can bind slack__search_messages into the Job tool set.
func (*UseCases) SlackService ¶
SlackService returns the Slack service (may be nil if not configured)
func (*UseCases) ValidateDB ¶
func (uc *UseCases) ValidateDB(ctx context.Context) (*ValidationResult, error)
ValidateDB validates that select/multi-select field values in the DB are consistent with the field schema defined in configuration. It uses count-based detection to avoid transferring document data, and only fetches a sample case when an inconsistency is found. It does NOT modify any data.
func (*UseCases) WebFetchClient ¶
WebFetchClient returns the agent webfetch client (nil when the tool is disabled or no LLM client is configured). Exposed so the Job runtime wiring can bind the same client into the Job tool set.
func (*UseCases) WorkspaceGroups ¶
func (uc *UseCases) WorkspaceGroups() *model.WorkspaceGroupRegistry
WorkspaceGroups returns the workspace group registry. It is never nil (New initializes an empty one), so callers can List() without a nil check.
func (*UseCases) WorkspaceRegistry ¶
func (uc *UseCases) WorkspaceRegistry() *model.WorkspaceRegistry
WorkspaceRegistry returns the workspace registry
type ValidationIssue ¶
type ValidationIssue struct {
WorkspaceID string
CaseID int64
FieldID string
Message string
Expected string
Actual string
}
ValidationIssue represents a single validation issue found during DB consistency check
type ValidationResult ¶
type ValidationResult struct {
Issues []ValidationIssue
}
ValidationResult holds the results of DB validation
func (*ValidationResult) AddIssue ¶
func (r *ValidationResult) AddIssue(issue ValidationIssue)
AddIssue adds a validation issue to the result
func (*ValidationResult) HasIssues ¶
func (r *ValidationResult) HasIssues() bool
HasIssues returns true if there are any validation issues
Source Files
¶
- action.go
- action_broadcast.go
- action_open.go
- action_step.go
- action_step_tool_adapter.go
- action_tool_adapter.go
- agent.go
- assist.go
- auth.go
- auth_cache.go
- auth_interface.go
- authn_noauthn.go
- case.go
- case_access.go
- case_tool_adapter.go
- case_welcome.go
- casemulti_tool_adapter.go
- dashboard.go
- errors.go
- field_coercion.go
- import.go
- job_run.go
- knowledge.go
- knowledge_tool_adapter.go
- memo.go
- memo_tool_adapter.go
- notification_slot.go
- reactioncase.go
- slack.go
- slack_command.go
- slack_command_save_draft.go
- slack_input_limits.go
- slack_mention_interaction.go
- slack_mention_modal.go
- slack_mention_proposal.go
- slack_mention_proposal_handler.go
- slack_mention_proposal_question.go
- slack_thread_create_question.go
- slack_thread_create_summary.go
- source.go
- tag.go
- threadcase.go
- uierr.go
- usecase.go
- validate.go
- workspace_agent.go
Directories
¶
| Path | Synopsis |
|---|---|
|
Package agent contains the Slack-independent agent runtime shared by the `casebound` (Case-bound mention) and `draft` (open-mode case draft) modes, and reserved for the future `triage` mode that will run after Case creation.
|
Package agent contains the Slack-independent agent runtime shared by the `casebound` (Case-bound mention) and `draft` (open-mode case draft) modes, and reserved for the future `triage` mode that will run after Case creation. |
|
casebound
Package casebound contains the agent runtime for case-bound channels — Slack channels that already have an associated Case.
|
Package casebound contains the agent runtime for case-bound channels — Slack channels that already have an associated Case. |
|
job
Package job is the event-driven Agent Job runtime.
|
Package job is the event-driven Agent Job runtime. |
|
planexec
Package planexec hosts the reusable plan-and-execute loop shared by the proposal (case-draft) host and the planexec-strategy Job host.
|
Package planexec hosts the reusable plan-and-execute loop shared by the proposal (case-draft) host and the planexec-strategy Job host. |
|
proposal
Package draft contains the open-mode (case-draft) agent runtime: a plan/execute loop that coordinates a planner LLM and parallel sub-agent investigations to produce a CaseProposal for the host (Slack) to render.
|
Package draft contains the open-mode (case-draft) agent runtime: a plan/execute loop that coordinates a planner LLM and parallel sub-agent investigations to produce a CaseProposal for the host (Slack) to render. |
|
threadcase
Package threadcase hosts the thread-mode agent: a plan-and-execute turn (planexec.Runner) that runs when a Case is created from a monitored channel post (materialize the Case fields) or when the bot is mentioned in a Case thread (investigate and respond / update fields / close).
|
Package threadcase hosts the thread-mode agent: a plan-and-execute turn (planexec.Runner) that runs when a Case is created from a monitored channel post (materialize the Case fields) or when the bot is mentioned in a Case thread (investigate and respond / update fields / close). |
|
wsagent
Package wsagent hosts the workspace-channel agent: a plan-and-execute turn (planexec.Runner) that runs when the bot is mentioned in a channel-mode workspace's configured workspace channel ([slack] workspace_channel).
|
Package wsagent hosts the workspace-channel agent: a plan-and-execute turn (planexec.Runner) that runs when the bot is mentioned in a channel-mode workspace's configured workspace channel ([slack] workspace_channel). |
|
Package diagnosis hosts data-repair and inspection routines that operate across the persistent state owned by the rest of the application.
|
Package diagnosis hosts data-repair and inspection routines that operate across the persistent state owned by the rest of the application. |
|
Package eval is the entry point of the offline eval harness: it loads scenario files, validates them (dry-run), runs each through its workflow driver, judges the produced artifact against the scenario checklist, dumps diagnostics for failing scenarios, and renders the aggregated report.
|
Package eval is the entry point of the offline eval harness: it loads scenario files, validates them (dry-run), runs each through its workflow driver, judges the produced artifact against the scenario checklist, dumps diagnostics for failing scenarios, and renders the aggregated report. |
|
driver
Package driver runs a workflow type for one scenario against a prepared env and returns the artifact to judge.
|
Package driver runs a workflow type for one scenario against a prepared env and returns the artifact to judge. |
|
env
Package env builds the in-memory environment a scenario runs against: a memory repository (seeded with the scenario's prior cases), in-memory history and trace repositories, the system-under-test wired via usecase.New, a recording fake Slack service, and per-tool clients that are either simulated (ToolSimulator) or live (recorded).
|
Package env builds the in-memory environment a scenario runs against: a memory repository (seeded with the scenario's prior cases), in-memory history and trace repositories, the system-under-test wired via usecase.New, a recording fake Slack service, and per-tool clients that are either simulated (ToolSimulator) or live (recorded). |
|
evaltype
Package evaltype holds the shared value types and small interfaces of the eval harness.
|
Package evaltype holds the shared value types and small interfaces of the eval harness. |
|
judge
Package judge evaluates a produced artifact against a scenario's checklist.
|
Package judge evaluates a produced artifact against a scenario's checklist. |
|
llmrun
Package llmrun provides the gollem-backed implementation of evaltype.Completer.
|
Package llmrun provides the gollem-backed implementation of evaltype.Completer. |
|
report
Package report aggregates scenario results and renders them: a human-readable stdout summary, a machine-readable JSON file, and per-scenario diagnostic dumps (see dump.go).
|
Package report aggregates scenario results and renders them: a human-readable stdout summary, a machine-readable JSON file, and per-scenario diagnostic dumps (see dump.go). |
|
scenario
Package scenario defines the TOML schema for eval scenarios and loads / validates them.
|
Package scenario defines the TOML schema for eval scenarios and loads / validates them. |
|
toolsim
Package toolsim provides simulated implementations of the agent's tool client interfaces.
|
Package toolsim provides simulated implementations of the agent's tool client interfaces. |
|
usersim
Package usersim implements evaltype.Simulator: a simulated end-user that answers the agent's clarification questions, drawing on the scenario persona (who they are + what they know).
|
Package usersim implements evaltype.Simulator: a simulated end-user that answers the agent's clarification questions, drawing on the scenario persona (who they are + what they know). |
|
Package export implements the `export` subcommand's core: reading the current state of every configured workspace out of the repository and writing it, one table per entity, to a pluggable Sink (BigQuery today).
|
Package export implements the `export` subcommand's core: reading the current state of every configured workspace out of the repository and writing it, one table per entity, to a pluggable Sink (BigQuery today). |
|
Package job hosts the event-driven Agent Job lifecycle: a usecase that publishes Events, matches them to workspace Jobs, and dispatches the Job runtime in a background goroutine.
|
Package job hosts the event-driven Agent Job lifecycle: a usecase that publishes Events, matches them to workspace Jobs, and dispatches the Job runtime in a background goroutine. |