p9: queue steps via agent.Core.Queue; yield message on plan
- queuePlanBackend now holds agent.Core and calls Queue() directly instead of writing to a filesystem path (enqueue is a virtual file) - fallback.core wired after NewAgentCore in createSession - Returns yield message so agent stops after planning and lets the queue drive execution step by step Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
8fa4a8e101
commit
8070238390
|
|
@ -3,30 +3,30 @@ package p9
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"ollie/pkg/agent"
|
||||||
"ollie/pkg/tools"
|
"ollie/pkg/tools"
|
||||||
)
|
)
|
||||||
|
|
||||||
// queuePlanBackend implements tools.PlanBackend by enqueuing each step as a
|
// queuePlanBackend implements tools.PlanBackend by enqueuing each step as a
|
||||||
// prompt into the session's queue file. It is used as the reasoning_plan
|
// prompt into the session's queue via agent.Core.Queue. It is used as the
|
||||||
// fallback when no task_create MCP tool is available.
|
// reasoning_plan fallback when no task_create MCP tool is available.
|
||||||
//
|
//
|
||||||
// Steps are enqueued in topological order (blockers before dependents). The
|
// Steps are enqueued in topological order (blockers before dependents). The
|
||||||
// goal description is prepended to the first step for context. Placeholder IDs
|
// goal description is prepended to the first step for context. Placeholder IDs
|
||||||
// ("q1", "q2", …) are returned so the agent can refer to steps by name.
|
// ("q1", "q2", …) are returned so the agent can refer to steps by name.
|
||||||
type queuePlanBackend struct {
|
type queuePlanBackend struct {
|
||||||
enqueuePath string // absolute path to the session's enqueue file
|
core agent.Core
|
||||||
}
|
}
|
||||||
|
|
||||||
// CreatePlan enqueues each plan step as a prompt. Steps with After dependencies
|
// CreatePlan enqueues each plan step as a prompt. Steps with After dependencies
|
||||||
// are sorted so blockers are enqueued before the steps that depend on them.
|
// are sorted so blockers are enqueued before the steps that depend on them.
|
||||||
// The returned IDs are positional placeholders ("q1", "q2", …).
|
// The returned IDs are positional placeholders ("q1", "q2", …).
|
||||||
func (b *queuePlanBackend) CreatePlan(_ context.Context, goal string, steps []tools.PlanStep) ([]string, error) {
|
func (b *queuePlanBackend) CreatePlan(_ context.Context, goal string, steps []tools.PlanStep) ([]string, string, error) {
|
||||||
order, err := topoSort(steps)
|
order, err := topoSort(steps)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("queue plan: %w", err)
|
return nil, "", fmt.Errorf("queue plan: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
ids := make([]string, len(steps))
|
ids := make([]string, len(steps))
|
||||||
|
|
@ -61,11 +61,15 @@ func (b *queuePlanBackend) CreatePlan(_ context.Context, goal string, steps []to
|
||||||
sb.WriteString(")")
|
sb.WriteString(")")
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := os.WriteFile(b.enqueuePath, []byte(sb.String()+"\n"), 0644); err != nil {
|
b.core.Queue(sb.String())
|
||||||
return nil, fmt.Errorf("enqueue step %s: %w", ids[idx], err)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return ids, nil
|
|
||||||
|
msg := fmt.Sprintf(
|
||||||
|
"Plan queued (%d steps). Stop here — do not execute. "+
|
||||||
|
"The queue will re-enter you with each step in order.",
|
||||||
|
len(steps),
|
||||||
|
)
|
||||||
|
return ids, msg, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// topoSort returns the indices of steps in topological order (blockers first).
|
// topoSort returns the indices of steps in topological order (blockers first).
|
||||||
|
|
|
||||||
|
|
@ -857,8 +857,7 @@ func (s *Server) createSession(args []string) error {
|
||||||
})
|
})
|
||||||
|
|
||||||
sessID := agent.NewSessionID()
|
sessID := agent.NewSessionID()
|
||||||
enqueuePath := s.sessionsDir + "/" + sessID + "/enqueue"
|
fallback := &queuePlanBackend{}
|
||||||
fallback := &queuePlanBackend{enqueuePath: enqueuePath}
|
|
||||||
env := agent.BuildAgentEnv(cfg, newDisp(), workdir, agent.WithFallbackPlanBackend(fallback))
|
env := agent.BuildAgentEnv(cfg, newDisp(), workdir, agent.WithFallbackPlanBackend(fallback))
|
||||||
|
|
||||||
ctx, cancel := context.WithCancel(context.Background())
|
ctx, cancel := context.WithCancel(context.Background())
|
||||||
|
|
@ -872,6 +871,7 @@ func (s *Server) createSession(args []string) error {
|
||||||
Env: env,
|
Env: env,
|
||||||
NewDispatcher: newDisp,
|
NewDispatcher: newDisp,
|
||||||
})
|
})
|
||||||
|
fallback.core = core
|
||||||
|
|
||||||
sess := &session{
|
sess := &session{
|
||||||
id: sessID,
|
id: sessID,
|
||||||
|
|
|
||||||
Reference in New Issue