Documentation
¶
Overview ¶
Package sidequestion captures immutable main-agent checkpoints. It never owns an agent session or a tool executor.
Index ¶
- Constants
- Variables
- func Attach(ctx context.Context, parent Parent, deps harness.QueryDeps, ...) (context.Context, harness.QueryDeps)
- func Bind(inner llm.Provider, model Model) llm.Provider
- func BuildRequest(s Snapshot, history []Exchange, question string) (llm.CompletionRequest, error)
- func CloneRequest(req llm.CompletionRequest) (llm.CompletionRequest, error)
- func EstimateInputTokens(req llm.CompletionRequest) int
- func Finish(ctx context.Context, messages []llm.Message)
- func IsSummaryRequest(req llm.CompletionRequest) bool
- func WithPublisher(ctx context.Context, publish Publisher) context.Context
- type Answer
- type Capture
- type ContextInfo
- type ContextOptions
- type Exchange
- type Memory
- type Model
- type Parent
- type Publisher
- type Replay
- type SideQuestionService
- type Snapshot
Constants ¶
const DefaultOutputTokens = 8192
const MaxRecentExchanges = 20
Variables ¶
var ErrContextBudget = errors.New("旁路上下文压缩后仍超过模型预算,请缩小问题范围或调整模型上下文配置")
Functions ¶
func Attach ¶
func Attach(ctx context.Context, parent Parent, deps harness.QueryDeps, provider llm.Provider) (context.Context, harness.QueryDeps)
Attach uses QueryDeps rather than a global provider hook so compaction and other auxiliary completions cannot replace the main conversation checkpoint.
func BuildRequest ¶
func CloneRequest ¶
func CloneRequest(req llm.CompletionRequest) (llm.CompletionRequest, error)
func EstimateInputTokens ¶
func EstimateInputTokens(req llm.CompletionRequest) int
EstimateInputTokens follows norma's byte-based block estimate with its 4/3 safety factor. Include system/schema and framing costs too; JSON characters are not tokens (and marshaling HTML can add many non-semantic escapes).
func Finish ¶
Finish adds tool results that landed after the final model request. Norma's first API message is its host reminder, absent from Terminal.Messages.
func IsSummaryRequest ¶ added in v0.3.56
func IsSummaryRequest(req llm.CompletionRequest) bool
IsSummaryRequest 报告这次 LLM 调用是不是「旁路摘要」请求。
用途:让调用方(比如 server 包的测试替身)能识别摘要请求,而**不依赖 thinking 参数**。
为什么不能用 thinking 当标记:摘要请求过去靠硬编码 thinking.type=disabled 来标记自己,但那个写法正是 adaptive thinking 模型会直接拒绝的 (上游 400 "requires adaptive thinking")。把判别式锚在 thinking 上,等于 「为了能被识别而写出一段会被拒的代码」——只能靠「请求被拒→重试」的 兜底才能工作,而这条路径的判别式已经失效了。
摘要请求的 system prompt 是固定的 summaryInstruction,这是它唯一且稳定的 身份标记。
Types ¶
type ContextInfo ¶
type ContextInfo struct {
Phase string `json:"phase,omitempty"`
RecentExchanges int `json:"recent_exchanges"`
HistorySummarized bool `json:"history_summarized"`
SnapshotSummarized bool `json:"snapshot_summarized"`
EstimatedInputTokens int `json:"estimated_input_tokens,omitempty"`
InputBudget int `json:"input_budget,omitempty"`
OutputTokens int `json:"output_tokens,omitempty"`
OverflowRetried bool `json:"overflow_retried,omitempty"`
}
type ContextOptions ¶
type ContextOptions struct{ OutputTokens int }
type Exchange ¶
type Exchange struct {
ID string `json:"id"`
SessionKey string `json:"-"`
ClientID string `json:"client_request_id"`
Generation int64 `json:"-"`
Question string `json:"question"`
Answer string `json:"answer"`
Status string `json:"status"`
Error string `json:"error,omitempty"`
Model Model `json:"model"`
SnapshotAt time.Time `json:"snapshot_at"`
CreatedAt time.Time `json:"created_at"`
Sequence int64 `json:"sequence"`
Usage llm.Usage `json:"usage"`
Ordinal int64 `json:"ordinal"`
Context ContextInfo `json:"context"`
}
type Memory ¶
type Memory struct {
History string `json:"history,omitempty"`
Through int64 `json:"through,omitempty"`
SnapshotKey string `json:"snapshot_key,omitempty"`
SnapshotSummary string `json:"snapshot_summary,omitempty"`
TailStart int `json:"tail_start,omitempty"`
}
Memory is independent of the main snapshot. Through is a persisted ordinal, not an array offset; restart, pagination and failed requests cannot shift it.
type Model ¶
type Model struct {
ProfileID int64 `json:"profile_id"`
Name string `json:"name"`
Format string `json:"format"`
Model string `json:"model"`
Identity string `json:"identity"`
Streaming bool `json:"streaming"`
WindowTokens int `json:"window_tokens"`
}
Model contains only configuration identity, never credentials or proxy URLs.
type Parent ¶
type Replay ¶
type Replay struct {
Memory Memory
Load func(context.Context, int64) ([]Exchange, error)
Save func(context.Context, Memory) error
}
Load returns ascending completed exchanges after the cursor, in bounded pages, restricted to ordinals before this request. Save must reject writes after a clear/delete/cancel using the admitted request's generation.
type SideQuestionService ¶
SideQuestionService has no harness, tool executor, transcript writer or model failover chain. Answer is one completion; Respond adds bounded preparation and at most one context-overflow recovery around that completion.
func (SideQuestionService) Answer ¶
func (s SideQuestionService) Answer(ctx context.Context, req llm.CompletionRequest, streaming bool, update func(Answer)) (out Answer, err error)
func (SideQuestionService) Respond ¶
func (s SideQuestionService) Respond(ctx context.Context, snapshot Snapshot, question string, replay Replay, options ContextOptions, update func(Answer, ContextInfo)) (out Answer, info ContextInfo, err error)
Respond owns preparation and at most one overflow recovery. No tools, main transcript or model-failover chain are introduced by the summary calls.