Changeset 0.17.0 (#75)

This commit is contained in:
2026-02-27 16:25:39 +00:00
parent 8bb77710b9
commit c9141a6896
37 changed files with 2778 additions and 968 deletions

View File

@@ -94,12 +94,14 @@ func (h *CompletionHandler) Complete(c *gin.Context) {
// ── Preset unwrap: preset overrides defaults, explicit request fields win ──
var presetSystemPrompt string
var personaID string // tracks active persona for KB scoping
if req.PresetID != "" {
preset := ResolvePreset(req.PresetID, userID)
preset := ResolvePreset(h.stores, req.PresetID, userID)
if preset == nil {
c.JSON(http.StatusBadRequest, gin.H{"error": "preset not found or not accessible"})
return
}
personaID = preset.ID
// Preset provides defaults; explicit request fields take priority
if req.Model == "" {
req.Model = preset.BaseModelID
@@ -138,7 +140,7 @@ func (h *CompletionHandler) Complete(c *gin.Context) {
}
// Load conversation history
messages, err := h.loadConversation(channelID, userID, presetSystemPrompt)
messages, err := h.loadConversation(channelID, userID, presetSystemPrompt, personaID)
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": "failed to load conversation"})
return
@@ -218,9 +220,9 @@ func (h *CompletionHandler) Complete(c *gin.Context) {
}
if stream {
h.streamCompletion(c, provider, providerCfg, provReq, channelID, userID, model, configID, providerScope)
h.streamCompletion(c, provider, providerCfg, provReq, channelID, userID, model, configID, providerScope, personaID)
} else {
h.syncCompletion(c, provider, providerCfg, provReq, channelID, userID, model, configID, providerScope)
h.syncCompletion(c, provider, providerCfg, provReq, channelID, userID, model, configID, providerScope, personaID)
}
}
@@ -356,9 +358,9 @@ func (h *CompletionHandler) streamCompletion(
provider providers.Provider,
cfg providers.ProviderConfig,
req providers.CompletionRequest,
channelID, userID, model, configID, providerScope string,
channelID, userID, model, configID, providerScope, personaID string,
) {
result := streamWithToolLoop(c, provider, cfg, &req, model, userID, channelID, h.hub)
result := streamWithToolLoop(c, provider, cfg, &req, model, userID, channelID, personaID, h.hub)
// Persist assistant response
if result.Content != "" {
@@ -380,7 +382,7 @@ func (h *CompletionHandler) syncCompletion(
provider providers.Provider,
cfg providers.ProviderConfig,
req providers.CompletionRequest,
channelID, userID, model, configID, providerScope string,
channelID, userID, model, configID, providerScope, personaID string,
) {
var totalInput, totalOutput int
var totalCacheCreation, totalCacheRead int
@@ -446,6 +448,7 @@ func (h *CompletionHandler) syncCompletion(
execCtx := tools.ExecutionContext{
UserID: userID,
ChannelID: channelID,
PersonaID: personaID,
}
for _, tc := range resp.ToolCalls {
call := tools.ToolCall{
@@ -747,7 +750,7 @@ func (h *CompletionHandler) resolveConfig(userID string, channelID string, req c
//
// Summary-aware: if the path contains a summary node (metadata.type = "summary"),
// messages before it are replaced by the summary content as a system message.
func (h *CompletionHandler) loadConversation(channelID, userID, presetSystemPrompt string) ([]providers.Message, error) {
func (h *CompletionHandler) loadConversation(channelID, userID, presetSystemPrompt, personaID string) ([]providers.Message, error) {
messages := make([]providers.Message, 0)
// ── Admin system prompt (always injected first, no opt out) ──
@@ -781,7 +784,7 @@ func (h *CompletionHandler) loadConversation(channelID, userID, presetSystemProm
}
// ── KB hint (nudge LLM to use kb_search when KBs are active) ──
if kbHint := BuildKBHint(context.Background(), h.stores, channelID, userID); kbHint != "" {
if kbHint := BuildKBHint(context.Background(), h.stores, channelID, userID, personaID); kbHint != "" {
messages = append(messages, providers.Message{
Role: "system",
Content: kbHint,