feat: update config, session manager, tools dag and subagent
This commit is contained in:
parent
45b525b832
commit
8b9fd30cd7
4 changed files with 67 additions and 1 deletions
|
|
@ -144,6 +144,14 @@ type ContinuityRetentionConfig struct {
|
|||
FailureKeepMessages int `json:"failure_keep_messages" env:"DRAGONSCALE_AGENTS_DEFAULTS_CONTINUITY_RETENTION_FAILURE_KEEP_MESSAGES"`
|
||||
}
|
||||
|
||||
// CompactionConfig controls the dual-threshold compaction control loop (LCM ADR-002).
|
||||
type CompactionConfig struct {
|
||||
// SoftThresholdPct triggers async background compaction (default 70).
|
||||
SoftThresholdPct int `json:"soft_threshold_pct" env:"DRAGONSCALE_AGENTS_DEFAULTS_COMPACTION_SOFT_THRESHOLD_PCT"`
|
||||
// HardThresholdPct triggers synchronous blocking compaction (default 90).
|
||||
HardThresholdPct int `json:"hard_threshold_pct" env:"DRAGONSCALE_AGENTS_DEFAULTS_COMPACTION_HARD_THRESHOLD_PCT"`
|
||||
}
|
||||
|
||||
type AgentDefaults struct {
|
||||
// Sandbox is the directory for agent file operations (tools sandbox).
|
||||
// Defaults to $XDG_DATA_HOME/dragonscale/sandbox when empty.
|
||||
|
|
@ -155,6 +163,7 @@ type AgentDefaults struct {
|
|||
Temperature float64 `json:"temperature" env:"DRAGONSCALE_AGENTS_DEFAULTS_TEMPERATURE"`
|
||||
MaxToolIterations int `json:"max_tool_iterations" env:"DRAGONSCALE_AGENTS_DEFAULTS_MAX_TOOL_ITERATIONS"`
|
||||
ContinuityRetention ContinuityRetentionConfig `json:"continuity_retention"`
|
||||
Compaction CompactionConfig `json:"compaction"`
|
||||
|
||||
// Deprecated: Use Sandbox instead. Kept for backward compatibility during migration.
|
||||
Workspace string `json:"workspace,omitempty" env:"DRAGONSCALE_AGENTS_DEFAULTS_WORKSPACE"`
|
||||
|
|
@ -373,6 +382,10 @@ func DefaultConfig() *Config {
|
|||
TargetContextRatio: 0.10,
|
||||
FailureKeepMessages: 10,
|
||||
},
|
||||
Compaction: CompactionConfig{
|
||||
SoftThresholdPct: 70,
|
||||
HardThresholdPct: 90,
|
||||
},
|
||||
},
|
||||
},
|
||||
Channels: ChannelsConfig{
|
||||
|
|
|
|||
|
|
@ -402,6 +402,27 @@ func (sm *SessionManager) persistMessageToDelegate(sessionKey string, msg messag
|
|||
map[string]interface{}{"session": sessionKey, "error": err.Error()})
|
||||
return
|
||||
}
|
||||
|
||||
// Dual-write: persist verbatim copy to immutable store (LCM ADR-001).
|
||||
immutableWriter, ok := sm.delegate.(interface {
|
||||
InsertImmutableMessage(ctx context.Context, msg *memory.ImmutableMessage) error
|
||||
})
|
||||
if ok {
|
||||
imMsg := &memory.ImmutableMessage{
|
||||
ID: ids.New(),
|
||||
SessionKey: sessionKey,
|
||||
Role: msg.Role,
|
||||
Content: msg.Content,
|
||||
ToolCallID: msg.ToolCallID,
|
||||
ToolCalls: toolCallsJSON(msg),
|
||||
TokenEstimate: estimateTokensSimple(msg.Content),
|
||||
}
|
||||
if err := immutableWriter.InsertImmutableMessage(ctx, imMsg); err != nil {
|
||||
logger.WarnCF("session", "Failed to persist immutable message",
|
||||
map[string]interface{}{"session": sessionKey, "error": err.Error()})
|
||||
}
|
||||
}
|
||||
|
||||
priorPtr, _ := sm.loadProjectionPointer(ctx, sessionKey)
|
||||
newPtr := advancePointer(priorPtr, item.ID, now)
|
||||
if err := sm.persistProjectionPointer(ctx, sessionKey, newPtr); err != nil {
|
||||
|
|
@ -729,3 +750,18 @@ func (sm *SessionManager) SetHistory(key string, history []messages.Message) {
|
|||
session.Updated = time.Now()
|
||||
}
|
||||
}
|
||||
|
||||
func toolCallsJSON(msg messages.Message) string {
|
||||
if len(msg.ToolCalls) == 0 {
|
||||
return ""
|
||||
}
|
||||
b, err := jsonv2.Marshal(msg.ToolCalls)
|
||||
if err != nil {
|
||||
return ""
|
||||
}
|
||||
return string(b)
|
||||
}
|
||||
|
||||
func estimateTokensSimple(content string) int {
|
||||
return (len(content) + 3) / 4
|
||||
}
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@ type DAGToolDeps struct {
|
|||
SessionFn func() string // returns current session key
|
||||
}
|
||||
|
||||
func recallRowToItem(row memsqlc.RecallItem) *memory.RecallItem {
|
||||
func recallRowToItem(row memsqlc.ListSessionMessagesPagedRow) *memory.RecallItem {
|
||||
return &memory.RecallItem{
|
||||
ID: row.ID,
|
||||
AgentID: row.AgentID,
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ package tools
|
|||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"log/slog"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
|
@ -186,6 +187,14 @@ func (sm *SubagentManager) Spawn(ctx context.Context, task, label, delegatedScop
|
|||
return "", fmt.Errorf("nested delegation requires delegated_scope and kept_work")
|
||||
}
|
||||
}
|
||||
if keptWork != "" {
|
||||
slog.Debug("delegation scope-reduction",
|
||||
"parent_depth", parentDepth,
|
||||
"child_depth", childDepth,
|
||||
"kept_work", keptWork,
|
||||
"delegated_scope", delegatedScope,
|
||||
)
|
||||
}
|
||||
if sm.runLoop == nil {
|
||||
sm.mu.Unlock()
|
||||
return "", ErrRunLoopNotConfigured
|
||||
|
|
@ -461,6 +470,14 @@ func (t *SubagentTool) Execute(ctx context.Context, args map[string]interface{})
|
|||
return ErrorResult("nested delegation requires delegated_scope and kept_work")
|
||||
}
|
||||
}
|
||||
if keptWork != "" {
|
||||
slog.Debug("delegation scope-reduction",
|
||||
"parent_depth", parentDepth,
|
||||
"child_depth", childDepth,
|
||||
"kept_work", keptWork,
|
||||
"delegated_scope", delegatedScope,
|
||||
)
|
||||
}
|
||||
|
||||
systemPrompt := "You are a subagent operating with main-loop control flow. Execute actions via tools, call discovered tools directly, and provide a clear concise result."
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue