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"`
|
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 {
|
type AgentDefaults struct {
|
||||||
// Sandbox is the directory for agent file operations (tools sandbox).
|
// Sandbox is the directory for agent file operations (tools sandbox).
|
||||||
// Defaults to $XDG_DATA_HOME/dragonscale/sandbox when empty.
|
// 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"`
|
Temperature float64 `json:"temperature" env:"DRAGONSCALE_AGENTS_DEFAULTS_TEMPERATURE"`
|
||||||
MaxToolIterations int `json:"max_tool_iterations" env:"DRAGONSCALE_AGENTS_DEFAULTS_MAX_TOOL_ITERATIONS"`
|
MaxToolIterations int `json:"max_tool_iterations" env:"DRAGONSCALE_AGENTS_DEFAULTS_MAX_TOOL_ITERATIONS"`
|
||||||
ContinuityRetention ContinuityRetentionConfig `json:"continuity_retention"`
|
ContinuityRetention ContinuityRetentionConfig `json:"continuity_retention"`
|
||||||
|
Compaction CompactionConfig `json:"compaction"`
|
||||||
|
|
||||||
// Deprecated: Use Sandbox instead. Kept for backward compatibility during migration.
|
// Deprecated: Use Sandbox instead. Kept for backward compatibility during migration.
|
||||||
Workspace string `json:"workspace,omitempty" env:"DRAGONSCALE_AGENTS_DEFAULTS_WORKSPACE"`
|
Workspace string `json:"workspace,omitempty" env:"DRAGONSCALE_AGENTS_DEFAULTS_WORKSPACE"`
|
||||||
|
|
@ -373,6 +382,10 @@ func DefaultConfig() *Config {
|
||||||
TargetContextRatio: 0.10,
|
TargetContextRatio: 0.10,
|
||||||
FailureKeepMessages: 10,
|
FailureKeepMessages: 10,
|
||||||
},
|
},
|
||||||
|
Compaction: CompactionConfig{
|
||||||
|
SoftThresholdPct: 70,
|
||||||
|
HardThresholdPct: 90,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
Channels: ChannelsConfig{
|
Channels: ChannelsConfig{
|
||||||
|
|
|
||||||
|
|
@ -402,6 +402,27 @@ func (sm *SessionManager) persistMessageToDelegate(sessionKey string, msg messag
|
||||||
map[string]interface{}{"session": sessionKey, "error": err.Error()})
|
map[string]interface{}{"session": sessionKey, "error": err.Error()})
|
||||||
return
|
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)
|
priorPtr, _ := sm.loadProjectionPointer(ctx, sessionKey)
|
||||||
newPtr := advancePointer(priorPtr, item.ID, now)
|
newPtr := advancePointer(priorPtr, item.ID, now)
|
||||||
if err := sm.persistProjectionPointer(ctx, sessionKey, newPtr); err != nil {
|
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()
|
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
|
SessionFn func() string // returns current session key
|
||||||
}
|
}
|
||||||
|
|
||||||
func recallRowToItem(row memsqlc.RecallItem) *memory.RecallItem {
|
func recallRowToItem(row memsqlc.ListSessionMessagesPagedRow) *memory.RecallItem {
|
||||||
return &memory.RecallItem{
|
return &memory.RecallItem{
|
||||||
ID: row.ID,
|
ID: row.ID,
|
||||||
AgentID: row.AgentID,
|
AgentID: row.AgentID,
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@ package tools
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"log/slog"
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"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")
|
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 {
|
if sm.runLoop == nil {
|
||||||
sm.mu.Unlock()
|
sm.mu.Unlock()
|
||||||
return "", ErrRunLoopNotConfigured
|
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")
|
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."
|
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