Persist workflow_instance_id, stage_instance_id, scope_kind on chat messages and task runs; resolve scope from live instance for chat and document tasks so refresh can apply consistent stage authorization. Co-authored-by: Cursor <cursoragent@cursor.com>
332 lines
15 KiB
Go
332 lines
15 KiB
Go
package ctxmgr
|
|
|
|
import (
|
|
"time"
|
|
|
|
"chat-agent-system/internal/storage"
|
|
)
|
|
|
|
// CommunicationStyle 用户沟通风格
|
|
type CommunicationStyle string
|
|
|
|
const (
|
|
StyleConciseStructured CommunicationStyle = "concise_structured" // 结构精炼、结论先行、拒绝冗长
|
|
StyleDetailedAnalytical CommunicationStyle = "detailed_analytical" // 详尽论证、全面对比、深挖细节
|
|
StyleExecutiveSummary CommunicationStyle = "executive_summary" // 高管要点、商业决策导向
|
|
)
|
|
|
|
// UserPreference 用户工作习惯与产出偏好画像
|
|
type UserPreference struct {
|
|
UserID int64 `json:"user_id"`
|
|
AccountID string `json:"account_id"`
|
|
Name string `json:"name"`
|
|
Role string `json:"role"`
|
|
CommunicationStyle CommunicationStyle `json:"communication_style"`
|
|
FocusAreas []string `json:"focus_areas"` // 关注维度,如 "reg_compliance", "cost_budget", "timeline", "optical_quality"
|
|
OutputFormatPref string `json:"output_format_pref"` // 报告格式要求,如 "standard_report", "bilingual_brief", "ppt_bullets"
|
|
CustomInstructions string `json:"custom_instructions"` // 用户直接指定的定制要求
|
|
MemoryFacts map[string]string `json:"memory_facts"` // 异步蒸馏出的长期事实记忆 (如 "预算通常按千万级申报", "偏好使用迈瑞作为对标竞品")
|
|
UpdatedAt time.Time `json:"updated_at"`
|
|
}
|
|
|
|
// ActivityItem 项目活动记录 (操作、决策、上传、下载)
|
|
type ActivityItem struct {
|
|
ID int64 `json:"id"`
|
|
ProjectID int64 `json:"project_id"`
|
|
UserID int64 `json:"user_id"`
|
|
UserName string `json:"user_name"`
|
|
ActivityType string `json:"activity_type"` // decision, operation, upload, download, stage_advance, chat
|
|
Title string `json:"title"`
|
|
Detail map[string]any `json:"detail,omitempty"`
|
|
RawWeight float64 `json:"raw_weight"` // 初始权重
|
|
DecayedWeight float64 `json:"decayed_weight"`// 时间衰减后当前有效权重
|
|
IsMilestone bool `json:"is_milestone"` // 里程碑事件不衰减
|
|
CreatedAt time.Time `json:"created_at"`
|
|
}
|
|
|
|
// TimeDecayConfig 时间权重衰减配置
|
|
type TimeDecayConfig struct {
|
|
Enabled bool `json:"enabled"`
|
|
HalfLifeDays float64 `json:"half_life_days"` // 半衰期天数 (如 7.0 天)
|
|
MinWeightFloor float64 `json:"min_weight_floor"` // 权重衰减下限 (如 0.10,防止被完全抹除)
|
|
MilestoneExempt bool `json:"milestone_exempt"` // 里程碑事件是否豁免衰减 (默认 true)
|
|
}
|
|
|
|
// DefaultTimeDecayConfig 默认时间衰减配置
|
|
func DefaultTimeDecayConfig() TimeDecayConfig {
|
|
return TimeDecayConfig{
|
|
Enabled: true,
|
|
HalfLifeDays: 7.0,
|
|
MinWeightFloor: 0.15,
|
|
MilestoneExempt: true,
|
|
}
|
|
}
|
|
|
|
// SingleUserContext 单用户私有上下文
|
|
type SingleUserContext struct {
|
|
UserID int64 `json:"user_id"`
|
|
AccountID string `json:"account_id"`
|
|
Name string `json:"name"`
|
|
Role string `json:"role"`
|
|
Preference *UserPreference `json:"preference"`
|
|
SessionID string `json:"session_id"`
|
|
RecentChats []ChatMessageRecord `json:"recent_chats"`
|
|
MyActivities []ActivityItem `json:"my_activities"`
|
|
MyFiles []*storage.FileReference `json:"my_files"`
|
|
AssembledAt time.Time `json:"assembled_at"`
|
|
}
|
|
|
|
// ProjectCollectiveContext 项目级多方协同上下文
|
|
type ProjectCollectiveContext struct {
|
|
ProjectID int64 `json:"project_id"`
|
|
ProjectCode string `json:"project_code"`
|
|
ProjectName string `json:"project_name"`
|
|
CurrentStage string `json:"current_stage"`
|
|
CreatorUserID int64 `json:"creator_user_id,omitempty"`
|
|
ActiveWorkflowKey string `json:"active_workflow_key,omitempty"`
|
|
WorkflowSelectionVersion int `json:"workflow_selection_version,omitempty"`
|
|
BlackboardFacts map[string]string `json:"blackboard_facts"`
|
|
AllActivities []ActivityItem `json:"all_activities"`
|
|
MilestoneDecisions []ActivityItem `json:"milestone_decisions"`
|
|
SharedFiles []*storage.FileReference `json:"shared_files"`
|
|
ParticipatingUsers []UserSummary `json:"participating_users"`
|
|
AssembledAt time.Time `json:"assembled_at"`
|
|
}
|
|
|
|
// UserSummary 参与项目的用户摘要
|
|
type UserSummary struct {
|
|
UserID int64 `json:"user_id"`
|
|
Name string `json:"name"`
|
|
Role string `json:"role"`
|
|
}
|
|
|
|
// ChatMessageRecord 结构化会话消息
|
|
type ChatMessageRecord struct {
|
|
ID int64 `json:"id"`
|
|
SessionID string `json:"session_id"`
|
|
UserID int64 `json:"user_id"`
|
|
Role string `json:"role"`
|
|
Content string `json:"content"`
|
|
Intent string `json:"intent,omitempty"`
|
|
Branch string `json:"branch,omitempty"`
|
|
Metadata map[string]any `json:"metadata,omitempty"`
|
|
DayKey string `json:"day_key"`
|
|
Category string `json:"category"`
|
|
ContentKind string `json:"content_kind,omitempty"`
|
|
ExportPolicy string `json:"export_policy,omitempty"`
|
|
ContentRevision int `json:"content_revision,omitempty"`
|
|
ContentSha256 string `json:"content_sha256,omitempty"`
|
|
WorkflowInstanceID int64 `json:"workflow_instance_id,omitempty"`
|
|
StageInstanceID int64 `json:"stage_instance_id,omitempty"`
|
|
StageKey string `json:"stage_key,omitempty"`
|
|
ScopeKind string `json:"scope_kind,omitempty"`
|
|
ExportCapability any `json:"export_capability,omitempty"`
|
|
DeletedAt *time.Time `json:"deleted_at,omitempty"`
|
|
CreatedAt time.Time `json:"created_at"`
|
|
}
|
|
|
|
// ChatDayBucket 按日消息分片桶
|
|
type ChatDayBucket struct {
|
|
DayKey string `json:"day_key"` // "2026-09-10"
|
|
Count int `json:"count"` // 当日消息总数(未截断)
|
|
LoadedCount int `json:"loaded_count"` // 本次实际返回条数
|
|
Truncated bool `json:"truncated"` // 单日超 MAX_MSG_PER_DAY 截断标记
|
|
FirstMessageID int64 `json:"first_message_id"` // 当日首条消息 ID
|
|
LastMessageID int64 `json:"last_message_id"` // 当日末条消息 ID
|
|
Messages []ChatMessageRecord `json:"messages"` // 正序
|
|
}
|
|
|
|
// ChatWindowQuery 按日窗口查询参数
|
|
type ChatWindowQuery struct {
|
|
SessionID string `json:"session_id"`
|
|
Days int `json:"days"` // 默认 7, 上限 31
|
|
BeforeDay string `json:"before_day"` // 触顶加载: 早于此日的下一段 (YYYY-MM-DD), 空则取最新
|
|
}
|
|
|
|
// ChatWindowResult 按日窗口查询结果
|
|
type ChatWindowResult struct {
|
|
SessionID string `json:"session_id"`
|
|
Days []ChatDayBucket `json:"days"` // 正序日集合
|
|
HasMoreBefore bool `json:"has_more_before"` // 是否存在早于 oldest_loaded_day 的消息
|
|
OldestLoadedDay string `json:"oldest_loaded_day"` // 当前已加载日中最旧的 day_key
|
|
}
|
|
|
|
// ChatDayMessagesResult 指定日消息拉取结果
|
|
type ChatDayMessagesResult struct {
|
|
SessionID string `json:"session_id"`
|
|
DayKey string `json:"day_key"`
|
|
TotalCount int `json:"total_count"`
|
|
LoadedCount int `json:"loaded_count"`
|
|
HasMoreBefore bool `json:"has_more_before"`
|
|
HasMoreAfter bool `json:"has_more_after"`
|
|
Messages []ChatMessageRecord `json:"messages"`
|
|
}
|
|
|
|
// ChatDateStat 会话日期统计 (用于日历打点)
|
|
type ChatDateStat struct {
|
|
DayKey string `json:"day_key"`
|
|
Count int `json:"count"`
|
|
Categories map[string]int `json:"categories"`
|
|
DigestStatus string `json:"digest_status,omitempty"` // 预留
|
|
}
|
|
|
|
// ChatCategoryStat 会话消息分类统计 (用于分类筛选条)
|
|
type ChatCategoryStat struct {
|
|
Category string `json:"category"`
|
|
Label string `json:"label"`
|
|
Count int `json:"count"`
|
|
FirstMessageID int64 `json:"first_message_id"`
|
|
LastMessageID int64 `json:"last_message_id"`
|
|
}
|
|
|
|
// BlendedSquadContext 智能体小队混合上下文 (用于注入到 Agent Prompt 中)
|
|
type BlendedSquadContext struct {
|
|
ProjectName string `json:"project_name"`
|
|
CurrentStage string `json:"current_stage"`
|
|
TaskKey string `json:"task_key"`
|
|
AgentRole string `json:"agent_role"`
|
|
BlackboardFacts map[string]string `json:"blackboard_facts"`
|
|
KeyDecisions []string `json:"key_decisions"`
|
|
RelevantFiles []string `json:"relevant_files"`
|
|
TriggerUserPreference *UserPreference `json:"trigger_user_preference,omitempty"`
|
|
PersonalizedGuidance string `json:"personalized_guidance"` // 针对当前用户偏好生成的注入指导语
|
|
AssembledAt time.Time `json:"assembled_at"`
|
|
}
|
|
|
|
// SessionFilter 历史会话查询过滤条件
|
|
type SessionFilter struct {
|
|
UserID int64 `json:"user_id,omitempty"`
|
|
ProjectID int64 `json:"project_id,omitempty"`
|
|
Limit int `json:"limit"`
|
|
Offset int `json:"offset"`
|
|
}
|
|
|
|
// ChatSessionSummary 会话摘要说明
|
|
type ChatSessionSummary struct {
|
|
SessionID string `json:"session_id"`
|
|
Title string `json:"title"`
|
|
UserID int64 `json:"user_id"`
|
|
ProjectID int64 `json:"project_id,omitempty"`
|
|
ProjectName string `json:"project_name,omitempty"`
|
|
MessageCount int `json:"message_count"`
|
|
LastMessage string `json:"last_message,omitempty"`
|
|
UpdatedAt time.Time `json:"updated_at"`
|
|
}
|
|
|
|
// CaseRecommendationItem 相似标杆案例自推荐条目
|
|
type CaseRecommendationItem struct {
|
|
DocID string `json:"doc_id"`
|
|
ProjectID int64 `json:"project_id"`
|
|
ProjectName string `json:"project_name"`
|
|
TaskKey string `json:"task_key"`
|
|
ArtifactTitle string `json:"artifact_title"`
|
|
SectionTitle string `json:"section_title"`
|
|
SummarySnippet string `json:"summary_snippet"`
|
|
KeyRegulations []string `json:"key_regulations,omitempty"`
|
|
SimilarityScore float64 `json:"similarity_score"`
|
|
ApprovedAt string `json:"approved_at"`
|
|
}
|
|
|
|
// CaseSearchOptions 标杆案例语义检索参数
|
|
type CaseSearchOptions struct {
|
|
Query string `json:"query"`
|
|
TaskKey string `json:"task_key,omitempty"`
|
|
ExcludeDoc string `json:"exclude_doc,omitempty"`
|
|
Limit int `json:"limit"`
|
|
MinScore float64 `json:"min_score"`
|
|
}
|
|
|
|
// MemoryChunkItem 语义记忆切片结构
|
|
type MemoryChunkItem struct {
|
|
ID int64 `json:"id"`
|
|
Domain string `json:"domain"`
|
|
ProjectID int64 `json:"project_id"`
|
|
UserID int64 `json:"user_id"`
|
|
ReferenceID string `json:"reference_id"`
|
|
Title string `json:"title"`
|
|
Content string `json:"content"`
|
|
ChunkHash string `json:"chunk_hash"`
|
|
Embedding []float32 `json:"embedding,omitempty"`
|
|
ImportanceWeight float64 `json:"importance_weight"`
|
|
Metadata map[string]any `json:"metadata,omitempty"`
|
|
CreatedAt time.Time `json:"created_at"`
|
|
}
|
|
|
|
// RestoredSessionContext 从持久化记录中重构的会话上下文
|
|
type RestoredSessionContext struct {
|
|
SessionID string `json:"session_id"`
|
|
UserID int64 `json:"user_id"`
|
|
ProjectID int64 `json:"project_id,omitempty"`
|
|
Title string `json:"title"`
|
|
Messages []ChatMessageRecord `json:"messages"`
|
|
Facts map[string]string `json:"facts,omitempty"`
|
|
}
|
|
|
|
// ChatSearchMode 检索模式
|
|
type ChatSearchMode string
|
|
|
|
const (
|
|
SearchModeKeyword ChatSearchMode = "keyword"
|
|
SearchModeFuzzy ChatSearchMode = "fuzzy"
|
|
SearchModeSemantic ChatSearchMode = "semantic"
|
|
SearchModeHybrid ChatSearchMode = "hybrid"
|
|
)
|
|
|
|
// ChatSearchQuery 搜索入参
|
|
type ChatSearchQuery struct {
|
|
SessionID string `json:"session_id"`
|
|
ProjectID int64 `json:"project_id,omitempty"`
|
|
UserID int64 `json:"user_id,omitempty"`
|
|
Query string `json:"query"`
|
|
Mode ChatSearchMode `json:"mode"` // 默认 hybrid
|
|
Category string `json:"category,omitempty"`
|
|
DateFrom string `json:"date_from,omitempty"`
|
|
DateTo string `json:"date_to,omitempty"`
|
|
Limit int `json:"limit"`
|
|
}
|
|
|
|
// ChatSearchHit 搜索命中
|
|
type ChatSearchHit struct {
|
|
MessageID int64 `json:"message_id"`
|
|
SessionID string `json:"session_id"`
|
|
DayKey string `json:"day_key"`
|
|
Role string `json:"role"`
|
|
Category string `json:"category"`
|
|
StageKey string `json:"stage_key,omitempty"`
|
|
Excerpt string `json:"excerpt"`
|
|
Score float64 `json:"score"`
|
|
MatchedBy string `json:"matched_by"`
|
|
}
|
|
|
|
// DigestDeliverable 当日交付物摘要
|
|
type DigestDeliverable struct {
|
|
DocID string `json:"doc_id"`
|
|
Title string `json:"title"`
|
|
State string `json:"state"`
|
|
}
|
|
|
|
// DailyDigest 按日智能摘要
|
|
type DailyDigest struct {
|
|
ID int64 `json:"id,omitempty"`
|
|
SessionID string `json:"session_id"`
|
|
ProjectID int64 `json:"project_id,omitempty"`
|
|
DayKey string `json:"day_key"`
|
|
Headline string `json:"headline"`
|
|
KeyPoints []string `json:"key_points"`
|
|
Deliverables []DigestDeliverable `json:"deliverables"`
|
|
Decisions []string `json:"decisions"`
|
|
OpenQuestions []string `json:"open_questions"`
|
|
StageProgress string `json:"stage_progress"`
|
|
FirstMessageID int64 `json:"first_message_id"`
|
|
LastMessageID int64 `json:"last_message_id"`
|
|
MessageCount int `json:"message_count"`
|
|
Status string `json:"status"` // pending | generating | ready | fallback | failed
|
|
Source string `json:"source"` // llm | rule
|
|
Model string `json:"model,omitempty"`
|
|
TokenUsage int `json:"token_usage,omitempty"`
|
|
DigestVersion int `json:"digest_version"`
|
|
GeneratedAt *time.Time `json:"generated_at,omitempty"`
|
|
UpdatedAt time.Time `json:"updated_at"`
|
|
}
|
|
|