Attach attaches a named context to the session, applying RAG semantics.
(name string, ragTopK, priority int)
| 98 | |
| 99 | // Attach attaches a named context to the session, applying RAG semantics. |
| 100 | func (a *contextPluginAdapter) Attach(name string, ragTopK, priority int) (string, error) { |
| 101 | mgr := a.manager() |
| 102 | if mgr == nil { |
| 103 | return "", fmt.Errorf("context manager unavailable in this session") |
| 104 | } |
| 105 | fc, err := mgr.GetContextByName(name) |
| 106 | if err != nil { |
| 107 | return "", fmt.Errorf("context %q not found — create it first with @context create", name) |
| 108 | } |
| 109 | if priority <= 0 { |
| 110 | priority = contextDefaultAttachPriority |
| 111 | } |
| 112 | |
| 113 | embeddings := mgr.RetrievalEnabled() |
| 114 | // Auto-RAG: a non-knowledge context attached without an explicit rag size, |
| 115 | // while embeddings are configured, becomes retrieval-first instead of a |
| 116 | // full-content dump. Knowledge mode already retrieves per turn, so it needs |
| 117 | // no override. |
| 118 | if ragTopK == 0 && embeddings && fc.Mode != ctxmgr.ModeKnowledge { |
| 119 | ragTopK = contextAutoRagTopK |
| 120 | } |
| 121 | |
| 122 | if err := mgr.AttachContextWithOptions(a.sessionID(), fc.ID, ctxmgr.AttachOptions{ |
| 123 | Priority: priority, |
| 124 | RetrievalTopK: ragTopK, |
| 125 | }); err != nil { |
| 126 | return "", err |
| 127 | } |
| 128 | |
| 129 | var b strings.Builder |
| 130 | fmt.Fprintf(&b, "Attached %q (mode=%s).", fc.Name, fc.Mode) |
| 131 | switch { |
| 132 | case fc.Mode == ctxmgr.ModeKnowledge: |
| 133 | if embeddings { |
| 134 | b.WriteString(" Retrieval: hybrid (keyless BM25 + embeddings).") |
| 135 | } else { |
| 136 | b.WriteString(" Retrieval: keyless BM25 (embeddings not configured).") |
| 137 | } |
| 138 | case ragTopK > 0: |
| 139 | fmt.Fprintf(&b, " Retrieval: semantic top-%d%s.", ragTopK, embeddingsNote(embeddings)) |
| 140 | default: |
| 141 | b.WriteString(" Injected as full content.") |
| 142 | } |
| 143 | if fc.Mode == ctxmgr.ModeKnowledge { |
| 144 | if digest := strings.TrimSpace(mgr.KnowledgeDigest(fc)); digest != "" { |
| 145 | b.WriteString("\n\n") |
| 146 | b.WriteString(digest) |
| 147 | } |
| 148 | b.WriteString("\nUse @knowledge to search/read it.") |
| 149 | } |
| 150 | return b.String(), nil |
| 151 | } |
| 152 | |
| 153 | // embeddingsNote annotates whether semantic retrieval has a vector backend. |
| 154 | func embeddingsNote(embeddings bool) string { |