feat: add natural elder story companion flow

This commit is contained in:
Codex Local
2026-09-06 20:16:01 +08:00
parent 029a6097a2
commit 8c834c0aa7
20 changed files with 582 additions and 149 deletions
+15 -11
View File
@@ -96,7 +96,10 @@ func (p *Processor) Handle(ctx context.Context, event outbox.Event) error {
// not cycle through retry and dead-letter queues forever.
return nil
}
content := joinedConversationContent(snapshot.turns)
// Only the subject's final turns can become a summary, story, fact, or
// continuation cue. Agent turns may contain questions or generated wording
// and must never be promoted into the subject's personal history.
content := joinedSubjectContent(sourceTurns)
generated, err := p.generateSafely(ctx, content, snapshot.tenantID)
if err != nil {
return err
@@ -250,14 +253,13 @@ func subjectTurns(turns []turn) []turn {
return items
}
func joinedConversationContent(turns []turn) string {
func joinedSubjectContent(turns []turn) string {
parts := make([]string, 0, len(turns))
for _, item := range turns {
label := "豆包"
if item.speaker == "subject" {
label = "长者"
if item.speaker != "subject" {
continue
}
parts = append(parts, label+":"+item.text)
parts = append(parts, "长者:"+item.text)
}
return strings.Join(parts, "\n")
}
@@ -284,11 +286,13 @@ func storeGeneration(ctx context.Context, tx pgx.Tx, conversationID string, snap
ON CONFLICT (conversation_id,summary_type,generation_version) DO NOTHING`, snapshot.tenantID, snapshot.subjectID, conversationID, summaryWithKeywords(generated.Summary, generated.Keywords), sourceJSON, generated.ModelRef, generated.PromptVersion, generationVersion, generated.Confidence); err != nil {
return fmt.Errorf("store conversation summary: %w", err)
}
if _, err := tx.Exec(ctx, `
INSERT INTO conversation_summary (tenant_id,subject_id,conversation_id,summary_type,content,source_turn_ids,model_ref,prompt_version,generation_version,confidence,status)
VALUES ($1::uuid,$2::uuid,$3::uuid,'open_topic',$4,$5::jsonb,$6,$7,$8,$9,'READY')
ON CONFLICT (conversation_id,summary_type,generation_version) DO NOTHING`, snapshot.tenantID, snapshot.subjectID, conversationID, generated.OpenTopic, sourceJSON, generated.ModelRef, generated.PromptVersion, generationVersion, generated.Confidence); err != nil {
return fmt.Errorf("store open topic: %w", err)
if strings.TrimSpace(generated.OpenTopic) != "" {
if _, err := tx.Exec(ctx, `
INSERT INTO conversation_summary (tenant_id,subject_id,conversation_id,summary_type,content,source_turn_ids,model_ref,prompt_version,generation_version,confidence,status)
VALUES ($1::uuid,$2::uuid,$3::uuid,'open_topic',$4,$5::jsonb,$6,$7,$8,$9,'READY')
ON CONFLICT (conversation_id,summary_type,generation_version) DO NOTHING`, snapshot.tenantID, snapshot.subjectID, conversationID, generated.OpenTopic, sourceJSON, generated.ModelRef, generated.PromptVersion, generationVersion, generated.Confidence); err != nil {
return fmt.Errorf("store open topic: %w", err)
}
}
if !generated.AllowStory {
return tx.Commit(ctx)