remove dead code: TaskState subsystem, Verbosity, dead session fields
Remove entire TaskState machinery: - TaskState struct, render(), taskState()/updateTaskState() on History - inferTaskStateUpdate() — heuristic plan tracking - Replan gate (replanGate const, roundsWithoutPlan counter) - Stall detection (stallThreshold, stallRounds, lastAction) - Plan reinject (planReinjectInterval, periodic re-injection) - ReadPlanStep plumbing (AgentCfg → Agent → TurnCtx → loop) None of this worked in practice — the model ignores the nudges, ReadPlanStep was never wired to a non-nil value, and TaskState fields were only populated by inferTaskStateUpdate (which depends on ReadPlanStep being set). Compaction now uses plain summary text in the cold zone instead of serialized TaskState JSON. Also remove: - Verbosity field (declared, threaded, never read by any backend) - DisallowTools (config field never wired to session) - Session.listHandlers, plan, prevPrompt (never read) - Config.Output, Config.ListHandlers, Config.ReadPlanStep (never set) -246 net lines
This commit is contained in:
parent
625654fcef
commit
5c81eefe0a
|
|
@ -51,7 +51,6 @@ type Agent struct {
|
|||
log *olog.Logger
|
||||
sessionID string // the owning session's ID
|
||||
startupMessages []string
|
||||
readPlanStep func() string
|
||||
save func() // trigger debounced persistence
|
||||
flush func() // immediately flush persistence
|
||||
onStateChange func(agentID, state string) // optional callback for state changes
|
||||
|
|
@ -76,14 +75,6 @@ func (ag *Agent) Messages() []backend.Message {
|
|||
return ag.history.history()
|
||||
}
|
||||
|
||||
// TaskState returns the current task state, if any.
|
||||
func (ag *Agent) TaskState() *TaskState {
|
||||
if ag.history == nil {
|
||||
return nil
|
||||
}
|
||||
return ag.history.TaskState
|
||||
}
|
||||
|
||||
// UsageStats holds token usage and cost information.
|
||||
type UsageStats struct {
|
||||
TotalInputTokens int
|
||||
|
|
@ -570,7 +561,6 @@ type AgentCfg struct {
|
|||
Output EventHandler
|
||||
Log *olog.Logger
|
||||
StartupMsgs []string
|
||||
ReadPlanStep func() string
|
||||
Save func()
|
||||
Flush func()
|
||||
}
|
||||
|
|
@ -594,7 +584,6 @@ func NewAgent(cfg AgentCfg) *Agent {
|
|||
log: cfg.Log,
|
||||
sessionID: cfg.SessionID,
|
||||
startupMessages: cfg.StartupMsgs,
|
||||
readPlanStep: cfg.ReadPlanStep,
|
||||
save: cfg.Save,
|
||||
flush: cfg.Flush,
|
||||
state: "idle",
|
||||
|
|
|
|||
|
|
@ -36,7 +36,6 @@ type AgentConfig struct {
|
|||
Tools *bool `json:"tools,omitempty"`
|
||||
AllowTools []string `json:"allowTools,omitempty"`
|
||||
AutoLoad []string `json:"autoLoad,omitempty"`
|
||||
DisallowTools []string `json:"disallowTools,omitempty"`
|
||||
MaxTokens int `json:"maxTokens,omitempty"`
|
||||
MaxCompletionTokens int `json:"maxCompletionTokens,omitempty"`
|
||||
// MaxSteps caps the number of tool-call rounds per turn. 0 means unlimited.
|
||||
|
|
@ -54,10 +53,8 @@ type AgentConfig struct {
|
|||
IncludeReasoning *bool `json:"includeReasoning,omitempty"`
|
||||
ResponseFormat string `json:"responseFormat,omitempty"`
|
||||
Stop []string `json:"stop,omitempty"`
|
||||
Verbosity string `json:"verbosity,omitempty"`
|
||||
CompactionModel string `json:"compactionModel,omitempty"`
|
||||
// SystemPrompt overrides the embedded system prompt with a file path.
|
||||
// If set and the file exists, its content replaces the compiled-in default.
|
||||
SystemPrompt string `json:"systemPrompt,omitempty"`
|
||||
}
|
||||
|
||||
|
|
@ -94,6 +91,5 @@ func (c *AgentConfig) GenParams() backend.GenerationParams {
|
|||
IncludeReasoning: c.IncludeReasoning,
|
||||
ResponseFormat: c.ResponseFormat,
|
||||
Stop: c.Stop,
|
||||
Verbosity: c.Verbosity,
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -36,45 +36,6 @@ Be concise. Capture what another LLM needs to seamlessly continue.`
|
|||
warmIndexSize = 10
|
||||
)
|
||||
|
||||
// TaskState is a compact structured overlay that summarizes the agent's
|
||||
// current position in a task. Injected at the top of every turn so the
|
||||
// model doesn't rely on full history recall.
|
||||
type TaskState struct {
|
||||
Objective string `json:"objective"`
|
||||
PlanStep string `json:"plan_step"`
|
||||
Constraints []string `json:"constraints,omitempty"`
|
||||
LastAction string `json:"last_action"`
|
||||
OpenQuestions []string `json:"open_questions,omitempty"`
|
||||
NextDecision string `json:"next_decision"`
|
||||
}
|
||||
|
||||
// render produces a compact text representation for injection into the message history.
|
||||
func (ts *TaskState) render() string {
|
||||
if ts.Objective == "" {
|
||||
return ""
|
||||
}
|
||||
var sb strings.Builder
|
||||
sb.WriteString("[task state]\n")
|
||||
sb.WriteString("objective: " + ts.Objective + "\n")
|
||||
if ts.PlanStep != "" {
|
||||
sb.WriteString("plan_step: " + ts.PlanStep + "\n")
|
||||
}
|
||||
if len(ts.Constraints) > 0 {
|
||||
sb.WriteString("constraints: " + strings.Join(ts.Constraints, "; ") + "\n")
|
||||
}
|
||||
if ts.LastAction != "" {
|
||||
sb.WriteString("last_action: " + ts.LastAction + "\n")
|
||||
}
|
||||
if len(ts.OpenQuestions) > 0 {
|
||||
sb.WriteString("open_questions: " + strings.Join(ts.OpenQuestions, "; ") + "\n")
|
||||
}
|
||||
if ts.NextDecision != "" {
|
||||
sb.WriteString("next_decision: " + ts.NextDecision + "\n")
|
||||
}
|
||||
sb.WriteString("[/task state]")
|
||||
return sb.String()
|
||||
}
|
||||
|
||||
// RestoreHistoryFromMessages reconstructs a History from just the message list.
|
||||
// Used for multi-agent session restore where each agent has separate messages.
|
||||
func RestoreHistoryFromMessages(messages []backend.Message) *History {
|
||||
|
|
@ -97,9 +58,8 @@ func RestoreHistoryFromMessages(messages []backend.Message) *History {
|
|||
|
||||
// History is an ephemeral in-memory state backend.
|
||||
type History struct {
|
||||
goal string
|
||||
messages []backend.Message
|
||||
TaskState *TaskState
|
||||
goal string
|
||||
messages []backend.Message
|
||||
// Cumulative usage tracking.
|
||||
TotalInputTokens int
|
||||
TotalCachedInputTokens int
|
||||
|
|
@ -128,14 +88,6 @@ func (s *History) history() []backend.Message {
|
|||
return s.messages
|
||||
}
|
||||
|
||||
func (s *History) taskState() *TaskState {
|
||||
return s.TaskState
|
||||
}
|
||||
|
||||
func (s *History) updateTaskState(ts TaskState) {
|
||||
s.TaskState = &ts
|
||||
}
|
||||
|
||||
func (s *History) addUsage(u backend.Usage, estimated bool) {
|
||||
s.TotalInputTokens += u.InputTokens
|
||||
s.TotalCachedInputTokens += u.CachedInputTokens
|
||||
|
|
@ -294,25 +246,16 @@ func (s *History) compact(ctx context.Context, b backend.Backend) (int, string,
|
|||
return 0, "", fmt.Errorf("compact: empty summary")
|
||||
}
|
||||
|
||||
// Parse structured task state from the model's JSON response.
|
||||
var ts TaskState
|
||||
raw := extractJSON(summaryText)
|
||||
if err := json.Unmarshal([]byte(raw), &ts); err != nil {
|
||||
// Fallback: treat as unstructured summary if JSON parse fails.
|
||||
ts = TaskState{Objective: summaryText}
|
||||
}
|
||||
s.TaskState = &ts
|
||||
|
||||
beforeCount := len(s.messages)
|
||||
s.messages = buildCompactedHistory(ts, s.messages)
|
||||
s.messages = buildCompactedHistory(summaryText, s.messages)
|
||||
return beforeCount - len(s.messages), summaryText, nil
|
||||
}
|
||||
|
||||
// buildCompactedHistory constructs a three-zone post-compaction message list:
|
||||
// - Cold: structured task state summary (everything older than warm+hot)
|
||||
// - Cold: compaction summary (everything older than warm+hot)
|
||||
// - Warm: brief index of recent decisions/actions (warmIndexSize messages)
|
||||
// - Hot: last hotTailSize messages verbatim
|
||||
func buildCompactedHistory(ts TaskState, allMessages []backend.Message) []backend.Message {
|
||||
func buildCompactedHistory(summary string, allMessages []backend.Message) []backend.Message {
|
||||
total := len(allMessages)
|
||||
|
||||
// Determine zone boundaries.
|
||||
|
|
@ -335,11 +278,10 @@ func buildCompactedHistory(ts TaskState, allMessages []backend.Message) []backen
|
|||
warmStart = 0
|
||||
}
|
||||
|
||||
// Cold zone: structured task state.
|
||||
stateJSON, _ := json.Marshal(ts)
|
||||
// Cold zone: compaction summary.
|
||||
cold := backend.Message{
|
||||
Role: "user",
|
||||
Content: "[compacted context — cold zone]\n```json\n" + string(stateJSON) + "\n```",
|
||||
Content: "[compacted context]\n" + summary,
|
||||
}
|
||||
|
||||
var out []backend.Message
|
||||
|
|
@ -399,31 +341,6 @@ func summarizeMessage(m backend.Message) string {
|
|||
}
|
||||
|
||||
// extractJSON finds the first JSON object in s (handling markdown fences).
|
||||
func extractJSON(s string) string {
|
||||
// Strip markdown code fence if present.
|
||||
if i := strings.Index(s, "```json"); i >= 0 {
|
||||
s = s[i+7:]
|
||||
if j := strings.Index(s, "```"); j >= 0 {
|
||||
s = s[:j]
|
||||
}
|
||||
} else if i := strings.Index(s, "```"); i >= 0 {
|
||||
s = s[i+3:]
|
||||
if j := strings.Index(s, "```"); j >= 0 {
|
||||
s = s[:j]
|
||||
}
|
||||
}
|
||||
// Find first { ... }
|
||||
start := strings.Index(s, "{")
|
||||
if start < 0 {
|
||||
return s
|
||||
}
|
||||
end := strings.LastIndex(s, "}")
|
||||
if end < start {
|
||||
return s
|
||||
}
|
||||
return s[start : end+1]
|
||||
}
|
||||
|
||||
// flattenToolMessages converts tool call/result sequences into plain text
|
||||
// so the compaction request doesn't include tool-specific structures that
|
||||
// the API may reject when no tools are defined.
|
||||
|
|
|
|||
126
agent/loop.go
126
agent/loop.go
|
|
@ -30,18 +30,6 @@ const (
|
|||
consecutiveErrorHardLimit = 10
|
||||
)
|
||||
|
||||
// replanGate is the max consecutive tool rounds without a PLAN: block before
|
||||
// a mandatory replan nudge is injected.
|
||||
const replanGate = 8
|
||||
|
||||
// stallThreshold is the number of consecutive rounds where LastAction doesn't
|
||||
// change before injecting a stall nudge.
|
||||
const stallThreshold = 5
|
||||
|
||||
// planReinjectInterval is the number of tool-call rounds between periodic
|
||||
// task state re-injection into the conversation.
|
||||
const planReinjectInterval = 10
|
||||
|
||||
type toolExecutor func(ctx context.Context, name string, args json.RawMessage) (string, []backend.ContentBlock, error)
|
||||
|
||||
// cachedResult stores a tool result with file metadata for staleness detection.
|
||||
|
|
@ -127,7 +115,6 @@ type TurnCtx struct {
|
|||
PopInject func() string // returns and clears pending inject, or ""
|
||||
AutoCompact func(ctx context.Context) // called after each tool round; may compact in-place
|
||||
Save func() // called after each state.update(); persists mid-turn progress
|
||||
ReadPlanStep func() string // next unchecked step from plan file, or ""
|
||||
IncrToolCallCount func() int64
|
||||
ResultCache *sync.Map
|
||||
}
|
||||
|
|
@ -135,9 +122,6 @@ type TurnCtx struct {
|
|||
func run(rt *Runtime, ctx TurnCtx, h *History) error {
|
||||
var step int
|
||||
var consecutiveErrors int // rounds where every tool call returned an error
|
||||
var roundsWithoutPlan int // consecutive tool rounds without a PLAN: block
|
||||
var lastAction string // previous round's LastAction for stall detection
|
||||
var stallRounds int // consecutive rounds with unchanged LastAction
|
||||
var lastErrorSig string // signature of previous round's error(s) for repeat detection
|
||||
var repeatErrorCount int // consecutive rounds with identical error signature
|
||||
// resultCache stores outputs of read-safe tool calls keyed by name+args.
|
||||
|
|
@ -160,12 +144,6 @@ func run(rt *Runtime, ctx TurnCtx, h *History) error {
|
|||
if preamble := rt.PreambleString(); preamble != "" {
|
||||
history = append([]backend.Message{{Role: "system", Content: preamble}}, history...)
|
||||
}
|
||||
if ts := h.taskState(); ts != nil {
|
||||
if msg := ts.render(); msg != "" && len(history) > 0 {
|
||||
// Insert after system prompt, before conversation.
|
||||
history = append([]backend.Message{history[0], {Role: "user", Content: msg}}, history[1:]...)
|
||||
}
|
||||
}
|
||||
|
||||
// Stream the assistant's response, retrying on rate limits, transient
|
||||
// backend errors (5xx, network), and mid-stream drops. One stable ID is
|
||||
|
|
@ -540,12 +518,6 @@ func run(rt *Runtime, ctx TurnCtx, h *History) error {
|
|||
h.update(msg, results)
|
||||
ctx.Save()
|
||||
|
||||
// Auto-update TaskState from what actually happened this round.
|
||||
if ts := h.taskState(); ts != nil {
|
||||
inferTaskStateUpdate(ts, msg, results, ctx.ReadPlanStep)
|
||||
h.updateTaskState(*ts)
|
||||
}
|
||||
|
||||
if interrupted {
|
||||
return ctx.Err()
|
||||
}
|
||||
|
|
@ -619,43 +591,7 @@ func run(rt *Runtime, ctx TurnCtx, h *History) error {
|
|||
lastErrorSig = ""
|
||||
}
|
||||
|
||||
// Replan gate: if the model has been calling tools without emitting a
|
||||
// PLAN: block, force it to replan before continuing.
|
||||
if strings.Contains(msg.Content, "PLAN:") {
|
||||
roundsWithoutPlan = 0
|
||||
} else {
|
||||
roundsWithoutPlan++
|
||||
}
|
||||
if roundsWithoutPlan >= replanGate {
|
||||
h.update(backend.Message{
|
||||
Role: "user",
|
||||
Content: fmt.Sprintf("<system-replan-required>\nYou have executed %d tool rounds without replanning. Stop and write a PLAN: block showing your current checklist before calling any more tools. Update session/$OLLIE_SESSION_ID/agent/$OLLIE_UNAME/plan.\n</system-replan-required>", replanGate),
|
||||
}, nil)
|
||||
roundsWithoutPlan = 0
|
||||
}
|
||||
|
||||
// Stall detection: if LastAction hasn't changed across rounds, the
|
||||
// model is likely stuck in a loop.
|
||||
if ts := h.taskState(); ts != nil {
|
||||
if ts.LastAction == lastAction && lastAction != "" {
|
||||
stallRounds++
|
||||
} else {
|
||||
stallRounds = 0
|
||||
}
|
||||
lastAction = ts.LastAction
|
||||
if stallRounds >= stallThreshold {
|
||||
h.update(backend.Message{
|
||||
Role: "user",
|
||||
Content: fmt.Sprintf("<system-stall-detected>\nYou have repeated the same action for %d rounds. Step back, reassess your approach, and try something different. Update your plan.\n</system-stall-detected>", stallRounds),
|
||||
}, nil)
|
||||
stallRounds = 0
|
||||
}
|
||||
}
|
||||
|
||||
// Reset step counter when an action-oriented tool is called successfully.
|
||||
// This allows the agent to continue working without hitting the soft
|
||||
// step-budget guardrail, as long as it's making active progress (writing
|
||||
// files, renaming symbols, etc.) rather than looping on research.
|
||||
if rt.ToolMeta != nil {
|
||||
for _, r := range results {
|
||||
if !r.IsError && rt.ToolMeta[r.Name].ResetsCounter {
|
||||
|
|
@ -666,8 +602,6 @@ func run(rt *Runtime, ctx TurnCtx, h *History) error {
|
|||
}
|
||||
|
||||
// Step budget warnings: nudge the agent at 50% and when exhausted.
|
||||
// These only fire for research-heavy loops — action tools (file_write,
|
||||
// file_edit, shell) reset the counter, so active progress never triggers.
|
||||
if rt.MaxSteps > 0 {
|
||||
halfBudget := rt.MaxSteps / 2
|
||||
if step == halfBudget {
|
||||
|
|
@ -685,19 +619,6 @@ func run(rt *Runtime, ctx TurnCtx, h *History) error {
|
|||
}
|
||||
}
|
||||
|
||||
// Periodic task state re-injection: every N tool rounds, surface the
|
||||
// structured task state back into the conversation to keep the model on track.
|
||||
if step > 0 && step%planReinjectInterval == 0 {
|
||||
if ts := h.taskState(); ts != nil {
|
||||
if msg := ts.render(); msg != "" {
|
||||
h.update(backend.Message{
|
||||
Role: "user",
|
||||
Content: "<system-task-state-review>\nReview your current task state and continue. Update it if your approach has changed.\n</system-task-state-review>\n\n" + msg,
|
||||
}, nil)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ctx.AutoCompact != nil {
|
||||
ctx.AutoCompact(ctx)
|
||||
}
|
||||
|
|
@ -727,53 +648,6 @@ func contextBudget(ctx context.Context, b backend.Backend) int {
|
|||
return ctxLen / 2
|
||||
}
|
||||
|
||||
// inferTaskStateUpdate updates TaskState fields from the actual tool round
|
||||
// without requiring model cooperation. Keeps the state current even if the
|
||||
// model ignores re-injection nudges.
|
||||
func inferTaskStateUpdate(ts *TaskState, msg backend.Message, results []toolResult, readPlanStep func() string) {
|
||||
// LastAction: summarize what tools ran and whether they succeeded.
|
||||
if len(msg.ToolCalls) > 0 {
|
||||
names := make([]string, 0, len(msg.ToolCalls))
|
||||
for _, tc := range msg.ToolCalls {
|
||||
names = append(names, tc.Name)
|
||||
}
|
||||
errCount := 0
|
||||
for _, r := range results {
|
||||
if r.IsError {
|
||||
errCount++
|
||||
}
|
||||
}
|
||||
action := strings.Join(names, ", ")
|
||||
if errCount > 0 {
|
||||
action += fmt.Sprintf(" (%d/%d failed)", errCount, len(results))
|
||||
}
|
||||
ts.LastAction = action
|
||||
}
|
||||
|
||||
// PlanStep: prefer the plan file (ground truth), fall back to text heuristic.
|
||||
if readPlanStep != nil {
|
||||
if step := readPlanStep(); step != "" {
|
||||
ts.PlanStep = step
|
||||
return
|
||||
}
|
||||
}
|
||||
// Fallback: extract from PLAN: block if present in assistant text.
|
||||
if idx := strings.Index(msg.Content, "PLAN:"); idx >= 0 {
|
||||
lines := strings.Split(msg.Content[idx:], "\n")
|
||||
for _, line := range lines[1:] {
|
||||
trimmed := strings.TrimSpace(line)
|
||||
if strings.HasPrefix(trimmed, "- [ ]") {
|
||||
ts.PlanStep = strings.TrimSpace(trimmed[5:])
|
||||
break
|
||||
}
|
||||
if trimmed == "" || (!strings.HasPrefix(trimmed, "- [") && trimmed != "") {
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// defaultToolResultMaxBytes caps tool result content sent back to the model.
|
||||
const defaultToolResultMaxBytes = 131072
|
||||
|
||||
|
|
|
|||
|
|
@ -120,10 +120,9 @@ func (ag *Agent) executeTurn(ctx context.Context, input string) string {
|
|||
}
|
||||
|
||||
turnCtx := TurnCtx{
|
||||
Output: ag.output,
|
||||
ReadPlanStep: ag.readPlanStep,
|
||||
Save: ag.save,
|
||||
ResultCache: &ag.resultCache,
|
||||
Output: ag.output,
|
||||
Save: ag.save,
|
||||
ResultCache: &ag.resultCache,
|
||||
}
|
||||
|
||||
var replyBuf strings.Builder
|
||||
|
|
|
|||
|
|
@ -138,7 +138,6 @@ type GenerationParams struct {
|
|||
IncludeReasoning *bool // include reasoning in response (OpenRouter)
|
||||
ResponseFormat string // "json_object", "text", etc.
|
||||
Stop []string // stop sequences
|
||||
Verbosity string // internal: controls output detail level
|
||||
}
|
||||
|
||||
// Backend is the interface all LLM providers must implement.
|
||||
|
|
|
|||
|
|
@ -34,7 +34,6 @@ type PersistedAgent struct {
|
|||
Model string `json:"model"`
|
||||
CWD string `json:"cwd"`
|
||||
Messages []backend.Message `json:"messages"`
|
||||
TaskState *agent.TaskState `json:"taskState,omitempty"`
|
||||
// Usage tracking
|
||||
TotalInputTokens int `json:"totalInputTokens,omitempty"`
|
||||
TotalCachedInputTokens int `json:"totalCachedInputTokens,omitempty"`
|
||||
|
|
@ -77,8 +76,7 @@ func PersistSession(name string) error {
|
|||
Backend: ag.BackendName(),
|
||||
Model: ag.ModelName(),
|
||||
CWD: ag.Cwd(),
|
||||
Messages: ag.Messages(),
|
||||
TaskState: ag.TaskState(),
|
||||
Messages: ag.Messages(),
|
||||
}
|
||||
if usage := ag.Usage(); usage != nil {
|
||||
pa.TotalInputTokens = usage.TotalInputTokens
|
||||
|
|
|
|||
|
|
@ -35,13 +35,10 @@ type Config struct {
|
|||
NewBackend func(string) (backend.Backend, error)
|
||||
Log *olog.Logger
|
||||
MaxSteps int
|
||||
ReadPlanStep func() string
|
||||
ListHandlers map[string]func() []string
|
||||
PromptEnvExtra []string
|
||||
Remote string
|
||||
SystemPrompt string
|
||||
EnvBlock string
|
||||
Output agent.EventHandler
|
||||
}
|
||||
|
||||
// Session owns all session-level state: identity, agents, tool server lifecycle.
|
||||
|
|
@ -60,26 +57,20 @@ type Session struct {
|
|||
Remote string
|
||||
|
||||
// Agent state
|
||||
agents []*agent.Agent
|
||||
log *olog.Logger
|
||||
sessionsDir string
|
||||
listHandlers map[string]func() []string
|
||||
agents []*agent.Agent
|
||||
log *olog.Logger
|
||||
sessionsDir string
|
||||
|
||||
// Environment
|
||||
envMu sync.RWMutex
|
||||
env map[string]string
|
||||
plan []byte
|
||||
prevPrompt string
|
||||
envMu sync.RWMutex
|
||||
env map[string]string
|
||||
|
||||
// Mutable state protected by mu
|
||||
mu sync.RWMutex
|
||||
name string // friendly name
|
||||
toolsConn *toolsrv.Conn // multiplexed RPC connection
|
||||
name string // friendly name
|
||||
toolsConn *toolsrv.Conn // multiplexed RPC connection
|
||||
paused bool
|
||||
|
||||
// Tool restrictions
|
||||
disallowTools map[string]struct{}
|
||||
|
||||
// Autosave
|
||||
saveMu sync.Mutex
|
||||
saveDirty bool
|
||||
|
|
@ -181,14 +172,13 @@ func New(cfg Config) *Session {
|
|||
}
|
||||
|
||||
s := &Session{
|
||||
ID: cfg.SessionID,
|
||||
name: name,
|
||||
Remote: cfg.Remote,
|
||||
env: make(map[string]string),
|
||||
agents: make([]*agent.Agent, 0, 1),
|
||||
log: log,
|
||||
sessionsDir: cfg.SessionsDir,
|
||||
listHandlers: cfg.ListHandlers,
|
||||
ID: cfg.SessionID,
|
||||
name: name,
|
||||
Remote: cfg.Remote,
|
||||
env: make(map[string]string),
|
||||
agents: make([]*agent.Agent, 0, 1),
|
||||
log: log,
|
||||
sessionsDir: cfg.SessionsDir,
|
||||
}
|
||||
|
||||
ag := agent.NewAgent(agent.AgentCfg{
|
||||
|
|
@ -203,11 +193,9 @@ func New(cfg Config) *Session {
|
|||
PromptEnvExtra: cfg.PromptEnvExtra,
|
||||
NewToolServer: cfg.NewToolServer,
|
||||
NewBackend: cfg.NewBackend,
|
||||
Output: cfg.Output,
|
||||
Log: log,
|
||||
SessionID: cfg.SessionID,
|
||||
StartupMsgs: rt.Messages,
|
||||
ReadPlanStep: cfg.ReadPlanStep,
|
||||
Save: s.saveSession,
|
||||
Flush: s.flushSave,
|
||||
})
|
||||
|
|
@ -405,12 +393,6 @@ func (s *Session) LoadTool(name string, ag *agent.Agent) error {
|
|||
if name == "" {
|
||||
return nil
|
||||
}
|
||||
s.mu.RLock()
|
||||
_, blocked := s.disallowTools[name]
|
||||
s.mu.RUnlock()
|
||||
if blocked {
|
||||
return fmt.Errorf("tool %q is disallowed for this session", name)
|
||||
}
|
||||
var conn *toolsrv.Conn
|
||||
if s.ToolsConn() != nil {
|
||||
conn = s.ToolsConn()
|
||||
|
|
|
|||
Loading…
Reference in New Issue