Documentation
¶
Overview ¶
Package ai implements kb's model probe, skill runner, and board tools over the local store.
Index ¶
- Constants
- Variables
- func ClampPriority(p int) int
- func NewHTTPClient() *http.Client
- func NewLinkClient() *http.Client
- func NormalizeStoryCount(max int) int
- func ProposeCardTool(c *CardCollector) tool.Tool
- func SkillBudget(maxTokens int64) int64
- func ValidateBaseURL(base string) error
- func ValidateDraft(d Draft) error
- type CardCollector
- type Config
- type Draft
- type DraftCheck
- type Error
- type RunResult
- type Runner
- func (r *Runner) FetchLinkTool() tool.Tool
- func (r *Runner) FindSimilarTool(user string) tool.Tool
- func (r *Runner) GetTaskTool(user string) tool.Tool
- func (r *Runner) ListTasksTool(user string) tool.Tool
- func (r *Runner) LoadSkills() ([]Skill, error)
- func (r *Runner) Probe(ctx context.Context, user string, supplied Config) error
- func (r *Runner) RunSkill(ctx context.Context, user string, scope Scope, skillName, input string, ...) (RunResult, error)
- func (r *Runner) RunText(ctx context.Context, user, system, prompt string, maxTokens int64) (string, error)
- func (r *Runner) UpdateTaskTool(user string) tool.Tool
- type Scope
- type Skill
Constants ¶
const ( TruncatedReplyMessage = "the model's reply hit the output limit and was cut off — ask for less in one request" ToolCallRequiredMessage = "model must support tool calling" )
const ( ProbeModelMissingMessage = "AI model not configured - fill in the model field" ProbeTimeoutMessage = "the AI endpoint did not answer before the test timed out" ProbeCancelledMessage = "the connection test was cancelled" ProbeDNSMessage = "the AI base URL host does not resolve - check the base URL" ProbeTLSMessage = "the AI endpoint's TLS handshake failed - check the scheme and the certificate" ProbeUnreachableMessage = "could not connect to the AI endpoint - check the base URL and that the server is running" ProbeOpaqueMessage = "upstream request failed" )
Probe failure messages. A connection test that cannot say what failed is a test the operator cannot act on, so each of these names both the thing that went wrong and the field that fixes it. They are shown verbatim in the settings overlay, so they stay one short sentence with no secret in them.
const ( UnknownSkillMessage = unknownSkillMessage SkillIterationLimitMessage = skillIterationLimitMessage )
const CardLimitReachedMessage = cardLimitReachedMessage
const RunnerSystemPrompt = runnerSystemPrompt
const SkillMaxIterations = skillMaxIterations
Variables ¶
var ErrPrivateAddress = errors.New("AI endpoint resolves to a private address (set KB_AI_ALLOW_PRIVATE=1 for local model servers)")
ErrPrivateAddress is the SSRF guard refusing a dial. It is a sentinel rather than an anonymous error because the message is the single most actionable thing the connection test can say - a local model server is the common case - and by the time the failure reaches the probe it has been through the dialer and transport, neither of which preserves error text.
Functions ¶
func ClampPriority ¶
func NewHTTPClient ¶
NewHTTPClient returns the guarded client used for model endpoints.
func NewLinkClient ¶
NewLinkClient returns the separately guarded client used by fetch_link.
func NormalizeStoryCount ¶
func ProposeCardTool ¶
func ProposeCardTool(c *CardCollector) tool.Tool
func SkillBudget ¶
SkillBudget clamps a requested completion budget to the supported range.
func ValidateBaseURL ¶
ValidateBaseURL applies the same endpoint validation used by model runs without constructing a client or reading a credential.
func ValidateDraft ¶
Types ¶
type CardCollector ¶
type CardCollector = cardCollector
CardCollector owns the structured card output for one tool loop.
func NewCardCollector ¶
func NewCardCollector(max int) *CardCollector
NewCardCollector creates a collector capped to one run's proposal budget.
type Draft ¶
type Draft struct {
Title string `json:"title"`
Emoji string `json:"emoji"`
Desc string `json:"desc"`
Prio int `json:"prio"`
Due string `json:"due"`
Effort string `json:"effort"`
Tags []string `json:"tags"`
Checks []DraftCheck `json:"checks"`
Source int `json:"-"`
}
Draft is one validated card proposal returned by a skill run.
func CoerceDraft ¶
type DraftCheck ¶
type Error ¶
Error carries a caller-facing category. Code retains status-shaped values for compatibility; local callers use Error.As and Error.Unwrap.
type RunResult ¶
type RunResult struct {
Cards []Draft `json:"cards"`
Commentary string `json:"commentary"`
Partial bool `json:"-"`
}
RunResult is one completed run: the cards the model proposed through propose_card, and its closing prose. Partial marks a run that hit a budget with cards already collected — the cards are real, the set is not complete. It stays out of JSON, so a caller that drops the commentary must preserve the partial marker separately.
type Runner ¶
type Runner struct {
// contains filtered or unexported fields
}
Runner owns the direct store and clients used by AI runs.
func NewRunner ¶
NewRunner constructs a direct-store runner. Nil clients select the guarded defaults; explicit clients are a test and embedding seam.
func (*Runner) FetchLinkTool ¶
func (*Runner) LoadSkills ¶
LoadSkills returns the built-in skills with the operator's directory layered on top. An override replaces the built-in with the same frontmatter name. The operator directory is optional, but a malformed existing catalogue is a whole-catalogue failure.
func (*Runner) Probe ¶
Probe validates either the stored AI configuration or supplied form values. Blank supplied fields retain the stored value. A stored key never travels to a newly supplied origin.
func (*Runner) RunSkill ¶
func (r *Runner) RunSkill(ctx context.Context, user string, scope Scope, skillName, input string, maxCards int, maxTokens int64) (RunResult, error)
runSkill executes one skill against the user's configured endpoint. The cards come from the collector the propose_card tool writes into, never from parsing the reply, so the model cannot smuggle a card past validateDraft and the count is capped by kb. maxTokens is the per-flow output budget: one card needs far less room than a whole ADR split, and the caller knows which flow it is.